Skip to content

docs: describe agent authority, broker trust boundaries, and implementation gaps - #2121

Open
jhrozek wants to merge 50 commits into
mainfrom
docs/agent-authority
Open

jhrozek wants to merge 50 commits into
mainfrom
docs/agent-authority

Conversation

@jhrozek

@jhrozek jhrozek commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Document the intended agent-identity and external-broker design, separating the
reader-facing explanation from implementation evidence and remaining work.

Design narrative

docs/agent-authority.md covers:

  • User, logical-agent and workload identities, including the limits of trusting
    a shared Mecatl process to identify its agents.
  • The A–D progression from Kubernetes ServiceAccount authentication to
    logical-agent credentials and SPIFFE workload authentication.
  • Interactive execution: broker admission for an exact call, followed by
    ToolHive token exchange using the existing user access token and a separate
    logical-agent credential.
  • Credential custody, account association, denial behavior and unknown outcomes.

Implementation companion

docs/agent-authority-implementation.md records inspected implementation
snapshots, gaps and follow-up decisions. It distinguishes existing functionality
from proposed integration rather than presenting the design as already shipped.

Scope

Documentation only. No runtime behavior changes.

The design retains the existing broker, browser authorization, token refresh and
provider credential custody. It does not introduce a new consent or mandate system.
Provider-credential linkage is an OAuth/ToolHive concern, separate from SPIFFE
workload authentication.

Review focus

  • Are the trust placed in Mecatl and the broker’s independent checks clear?
  • Are user, agent and workload identities kept distinct throughout the flow?
  • Does the intended design preserve exact-call authorization independently of
    OAuth token claims?
  • Does the companion accurately identify what remains unresolved?

Validation

  • Staged whitespace checks passed.
  • task docs ran but did not pass link validation.
  • The companion references a document absent from the branch and two ToolHive
    follow-up briefs not included in this commit; those links need resolution
    before merge.

@jhrozek
jhrozek force-pushed the docs/agent-authority branch from bca7cf8 to 8c6f099 Compare October 5, 2026 22:28
Comment thread docs/agent-authority.md Outdated
@jhrozek
jhrozek force-pushed the docs/agent-authority branch from 8c6f099 to 70e62b9 Compare October 6, 2026 10:12
Comment thread docs/agent-authority.md Outdated

@JAORMX JAORMX left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jakub, my main concern here is keeping the agent/subagent hierarchy from the existing identity model:

https://github.com/stacklok/mecatl/blob/main/docs/agent-identity-model.md#the-three-tier-model

I'm fine with code-reviewer being a stable logical identity that we can use in policy. But we also need to know which instance of that reviewer we're talking about and where it sits in the delegation tree:

Alice
└── main
    └── code-reviewer
        └── security-reviewer
            └── another specialist

Each child inherits restrictions from its parent, all the way down. If the main agent was restricted to reviewing PR 42, spawning a specialist with a broader definition must not give it access to other repositories or permission to merge.

The document does say children only narrow authority. What I'm missing is how we carry and enforce that hierarchy through issuance, broker admission and recovery. The credential identifies the definition, and then we have separate run and call bindings, but where is the binding to the actual parent and the authority delegated to this particular child?

I'm not asking for a private key per subagent or claiming this isolates goroutines from a compromised Mecatl process. I want us to preserve the delegation tree as something we enforce, rather than something we only reconstruct from logs.

Can we make that relationship explicit before settling the credential model? I'd like the broker flow to implement the definition/instance/run model, rather than leave the instance hierarchy behind.

Comment thread docs/agent-authority.md Outdated
Comment thread docs/agent-authority.md Outdated
Comment thread docs/agent-authority.md Outdated
@JAORMX

JAORMX commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

One clarification on my earlier comments: I’m thinking of this in two phases. First, identities and cryptographically verifiable attribution across the agent/subagent tree, so we can audit which instance did what and beneath whom. Then, policy enforcement where each child’s authority stays within what its parent may delegate.

I see this PR as helping with that first foundation. I’m not asking us to settle the policy language or containment mechanism here, or make the complete enforcement model a prerequisite for attribution. I want us to preserve the hierarchy now so enforcement can build on the same model later.

@JAORMX

JAORMX commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Jakub, one more thing I'd like us to account for is agent definition provenance. This expands the scope a bit, so I'm not asking us to implement every source adapter or settle a wire format in this PR. But I think we should capture the requirement on both the Mecatl side and the identity broker side.

For attribution, I'd like to answer: which agent definition revision did this particular agent instance actually use, and where did it come from?

With local files, that could mean repository, path, commit and content digest. But Mecatl's AgentDefSource is deliberately storage-independent. An agent definition could also come from a Kubernetes custom resource or a service backed by Postgres. The provenance contract should support those sources without making Git or Kubernetes concepts part of the core interface.

Could we leave room for an agent definition provenance envelope with extensible metadata and versioned profiles? Something like this, just to illustrate the shape:

agent_definition_provenance:
  profile: mecatl.agent-definition-provenance.git/v1
  metadata:
    repository: https://github.com/example/agents
    path: agents/reviewer.md
    commit: "<full commit ID>"
    source_content_digest:
      algorithm: sha256
      value: "<digest of the source content>"
    accepted_definition_digest:
      algorithm: sha256
      value: "<digest of the normalized agent definition>"

A Kubernetes profile could describe the source cluster, custom-resource object UID, observed revision and relevant-content digest. A service-backed profile could use a service/tenant namespace, object identifier and revision. Those are source details; the workload running the agent has its own identity and runtime metadata.

I'm fine with the metadata being a map, provided each profile has a strict contract: required fields, schemas, hashing rules and defined revision semantics. The operator should be able to require particular evidence, and the source shouldn't be able to weaken those requirements by selecting a more permissive profile.

The distinction between source content and the accepted agent definition matters here. Mecatl parses and normalizes agent definitions, so the bytes read aren't necessarily the exact representation used to construct the agent. Having a commit and a digest also doesn't establish that the loaded content belongs to that commit. A locally modified file is an obvious example.

The flow I have in mind is:

Source adapter/service
  → agent definition + source evidence
Mecatl's trusted resolver
  → accepted definition snapshot + validated provenance
Mecatl's instance lifecycle
  → bind that snapshot to the instance and its parent
Identity broker
  → validate required evidence and establish a verifiable binding
Invocation/audit records
  → retain the link to that instance and provenance

This information should come from source resolution and trusted execution state, not from the model. The agent definition and its provenance need to describe the same snapshot. We shouldn't reconstruct provenance afterward by looking at whatever happens to be current in Git, Kubernetes or the service.

On the broker side, we should distinguish what it verifies independently from what it accepts as Mecatl's attestation. “Mecatl reports loading these bytes from commit X” is different from “the broker verified these bytes against commit X.” We don't need the broker to access every backend, but its signature shouldn't obscure that trust distinction.

I also don't think the full provenance record needs to be a claim in every token. We could embed it or use an integrity-protected reference to retained evidence. If the logical-agent credential is reusable across instances, the binding needs to live in instance-specific evidence or an authenticated broker record instead. Otherwise, one credential could end up describing several different agent definition revisions ambiguously.

This fits the observability-first phase: establish which agent definition each instance used and preserve that evidence alongside the delegation hierarchy. It doesn't grant permissions by itself. Later, enforcement could require approved revisions or particular source authorities.

Can we capture this in the proposal and track the Mecatl interface and broker work separately? I'd like us to preserve enough information now that verifiable attribution doesn't stop at the agent definition's name and admission tier.

@jhrozek
jhrozek force-pushed the docs/agent-authority branch 2 times, most recently from 8c1f133 to 1b69f1a Compare October 12, 2026 11:59
@JAORMX

JAORMX commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

So, I think we're mixing two threat models here. With native execution enabled, mecak8s already keeps workspace filesystem operations and Shell in separate executor Pods, behind the execution provider. A prompt-injected agent running a command doesn't automatically get access to the mecak8s process or its credentials. The proposal acknowledges that existing boundary, but I'd like that distinction to drive the rationale throughout.

I'm in favor of brokerage, and I want the real provider credentials kept away from mecak8s. I also want to keep the agent loop minimal. Owning OAuth enrollment, account association, refresh, credential selection, and mediated provider calls is plenty of responsibility for a broker already!

I don't have a strong opinion about whether that needs its own deployment. A separate deployment is fine for operational ownership, independent lifecycle, or sharing the service across instances. But I wouldn't make process separation the main security argument for the identity design. Keeping credentials outside mecak8s can reduce exposure if that process is compromised, provided its storage and deployment permissions are actually separated. That's a useful property, but it's a different threat from hostile code running in an executor.

And moving the signer doesn't make the identity reports independently trustworthy. If we trust mecak8s to report the user, agent instance, and delegation context, that trust remains. A compromised process holding multiple agent credentials can still substitute one for another. The docs already acknowledge this, and I think we should make it part of the starting assumptions rather than something readers discover after the architecture.

I'd frame this around the responsibilities first: the loop runs agents, the existing execution boundary handles workspace code, and the broker owns provider connections and protected external calls. Identity issuance can be a module in that design without implying another service or per-agent process isolation.

The part I'd like us to discuss separately is broker ownership of run admission and agent lifecycle. Establishing bounded access to external tools makes sense. Becoming another authority over whether agents can start or runs can execute is a much larger decision. Can we clarify which one we mean, and keep the attribution work from depending on the broader execution-control design?

@jhrozek
jhrozek force-pushed the docs/agent-authority branch 2 times, most recently from c3f50e7 to c3f3fa7 Compare October 12, 2026 12:57
jhrozek and others added 10 commits October 12, 2026 19:26
Co-authored-by: Mecatl <noreply@mecatl.dev>
Co-Authored-By: Mecatl <noreply@mecatl.dev>
Co-authored-by: Mecatl <noreply@mecatl.dev>
Preserve the reviewed broker-centered design and implementation notes, and mark the old identity model superseded with unresolved migration work explicit.

Co-authored-by: Mecatl <noreply@mecatl.dev>
Co-authored-by: Mecatl <noreply@mecatl.dev>
Clarify definition and instance lifecycle, show main and reviewer tool calls, and scope Cedar v1 to definition-derived MCP ceilings. Expand audit requirements and add the future all-tool mediation chapter.

Co-authored-by: Mecatl <noreply@mecatl.dev>
Describe one protocol for reaching a ToolHive vMCP gateway in embedded and
external mode: the broker's grant issuer (AS-1) signs an identity-chaining
grant that the gateway's authorization server (AS-2) redeems. Split the
README diagram into broker and gateway, and list the pending changes to the
credentials walkthrough.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Remove the former identity model, authority design, and implementation notes,
now superseded by the broker-centered design in docs/drafts/agent-identity/.
Point the drafts index and companion drafts at the new design and mark the
outbound draft as historical; the removed documents remain in Git history.

Co-Authored-By: mecatl <noreply@mecatl.dev>
@jhrozek
jhrozek force-pushed the docs/agent-authority branch from c3f3fa7 to f75b378 Compare October 12, 2026 17:35
jhrozek and others added 2 commits October 12, 2026 19:56
Clarify lifecycle placement and identity terminology, align the overview with the two-call walkthrough, and replace repeated authorization and audit details with links to their owning chapters.

Co-authored-by: Mecatl <noreply@mecatl.dev>
Narrow each child at the broker: registration stores an effective
server/tool ceiling, the definition ceiling intersected with the
parent's, and Cedar evaluates it. A deployer spawned under a read-only
reviewer can no longer merge, and renewal and restoration reload the
stored set instead of recomputing it.

Define execution context: workload, instance, and session are verified;
user, run, and delegation are mecak8s-reported and not v1 Cedar inputs.
This resolves the walkthrough contradicting the binding requirement.

Add definition provenance (versioned profiles, source and accepted
digests, verified versus asserted facts) with Mecatl and broker work
items. Document the built-in system/main and system/explorer
definitions for sessions without an AgentDef, state that mecak8s is a
trusted rather than independently verified attestor, add Workload and
Execution context to the glossary, qualify bare "agent identity", and
fix the root README link to the retired identity model draft.

Co-Authored-By: mecatl <noreply@mecatl.dev>
@jhrozek

jhrozek commented Oct 13, 2026

Copy link
Copy Markdown
Contributor Author

Replies to the review summary and the first two issue comments, as of fbf9e8d.

Review summary (delegation hierarchy through issuance, admission and recovery). The hierarchy is now enforced at the broker, not only reconstructed from logs. Each instance is registered under its parent. The broker stores an effective ceiling equal to the child's definition ceiling intersected with the parent's, evaluates it on every call, and reloads it unchanged on renewal and recovery. Details are in Delegated authority and the thread replies above.

Two phases (attribution, then enforcement). Phase 1 maps onto the audit evidence table and the illustrative authorization record. They attribute each call to its instance, incarnation, definition revision, creation parent, run, delegation and user, and mark which facts are verified and which are reported. Server/tool enforcement against the parent's ceiling landed in v1 as well. Still deferred: task-specific bounds, resource/argument policy, and a verified per-operation binding for the reported run and delegation fields.

Agent definition provenance. Captured in a new Definition provenance section:

  • a versioned profile with profile-specific metadata (Git, Kubernetes CR, or service-backed), keeping AgentDefSource storage-independent;
  • strict per-profile contracts, with operator-required evidence that a source can't downgrade;
  • separate source-content and accepted-definition digests, with the locally-modified-file caveat;
  • provenance from the trusted resolver, never reconstructed later;
  • broker-verified facts kept distinct from mecak8s-asserted ones;
  • provenance stored in the per-instance registration record rather than in tokens.

Mecatl and broker work are tracked separately in implementation.md. No wire format is chosen.

The 2026-10-12 comment on threat models and broker scope is still under discussion.

jhrozek and others added 8 commits October 15, 2026 15:28
Signing out of one client and stopping agents are different actions.
"Sign out" revokes only that client's tokens. "Sign out everywhere"
stops every agent acting for the user: live runs, parked and in-flight
tool calls, broker sessions and their refresh tokens, and every
schedule's authority.

AS-1 also re-checks the company-IdP refresh token behind each grant when
it issues an ID-JAG, at most once per interval. A refusal revokes all
the user's grants, so a disabled account stops acting at any IdP that
issues refresh tokens, without IdP events.

Record the decision as D8, size the ToolHive work, add the checks, and
list IdP events, login-session binding, and Shared Signals as later
work.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Replace the illustrative evidence table with a profile of toolhive-core
audit.AuditEvent: what goes in each field, a fixed outcome set per event
type, issuer-qualified credential references, provenance marks for each
identity, operation and attempt correlation, creation and delegation
lineage kept apart from the act chain, and the event families the
identity work needs. Interim keys use the mecatl. namespace until
toolhive-core#341 and #342 land. Add round-trip checks to the
implementation companion.

AS-1 now sets act.iss to its own issuer, so agent: identifiers stay
attributable to AS-1 after AS-2 copies act into V (D4).

Mark the ToolHive work list as the ledger of ToolHive changes, none
filed yet, and add the operation-ID recording, missing-upstream-record,
and vMCP session revocation rows.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Add registration and delegation events that link each instance to its
creation parent and each delegation to its parent delegation by
AuditID. They follow the audit retention period rather than the
session, so an investigator can reconstruct main to reviewer to
specialist after a restart or session cleanup, and an unresolved link
is reported as an incomplete chain. Tool-call events now reference
their delegation instead of inlining it.

mecak8s reports each delegation to the broker when it happens. Add the
reconstruction checks to the implementation companion.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Every component records through the toolhive-core audit logger, whose
sink the deployment points at a store mecak8s cannot write or delete;
records delivered before a compromise survive even while the broker
runs inside mecak8s. ToolHive's authorization server records nothing
today, and the ledger row now includes sign-in and token issuance.

Add the producers of each event family, the broker's write order
(decision accepted by the sink before dispatch, otherwise no dispatch),
contiguous per-stream sequence numbers, cross-store reconciliation
checks, broker consistency checks on reported lineage, retention rules,
and coverage. Add a provenance mark for a verified credential whose
binding mecak8s reported. Hash chains and signed records stay later
work.

Co-Authored-By: mecatl <noreply@mecatl.dev>
The rework record was an intermediate step that kept collecting
decisions. Move what only it held into the owning chapters: the
chained-exchange plan and why act is not nested now (MCP
authorization), why the agent SVID stays and its possible
strengthenings (credentials walkthrough), the pluggable roles for
standalone and enterprise deployments (gateway modes), and what the
user sees. Repoint its links and delete it; the ToolHive ledger in the
implementation companion replaces its gaps table.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Section 9.3 scopes the profile to parties in different trust domains;
it does not just require separate issuers and keys. External mode fits
that scope. Embedded mode shares one trust domain, reuses the ID-JAG
format for one protocol path, still meets the requirement that AS-1
never issues an access token from its own ID-JAG, and bounds scope
broadening because AS-2 issues V only for the vMCP resource.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Only mecak8s checked that the user owns the session it opens, so a bug
could pair one user's token with another user's session. AS-1 now
converts the token only if its sub_id equals the owner mecak8s sends,
records the owner at the first open, and refuses later opens for a
different user; session IDs are never reused. These checks catch
mistakes, not a compromised mecak8s.

Record session-bound tokens (RFC 9396 authorization_details obtained by
the client at session creation) as later work, with the client token
handling in the TUI and Studio to check first, and add the ToolHive
ledger rows. The ID-JAG and everything downstream are unchanged.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Ceilings set by the definition loader stop mecak8s from supplying fake
definitions, but mecak8s still picks which definition is a session's
root. The operator's loader configuration therefore names the
root-eligible definitions, optionally per user or group, and caps the
ceiling of definitions from other sources, so no reported parent or
agent can exceed the widest root-eligible ceiling.

Add run grants as authority work: a grant per run, minted from a fresh
user access token, so sessions of absent users carry no authority.

Co-Authored-By: mecatl <noreply@mecatl.dev>
@jhrozek

jhrozek commented Oct 15, 2026

Copy link
Copy Markdown
Contributor Author

This round of review comments is answered, and each thread has a reply linking the commit. I've left the threads open so you can resolve them, or push back if a reply doesn't settle it.

Answers to review comments

  • Sequencing (@ChrisJBurns, @JAORMX). The identity work comes first and has no broker authority in it; the authority work follows. "v1" is gone from the drafts (eede8bd).
  • Deployment and threats (@JAORMX, 10-12). The broker starts as modules inside mecak8s and later becomes a separate service. A new section says what each deployment closes against a compromised mecak8s, and what stays mecak8s's word in both. Run admission is now an explicit non-goal (adae397, 81eae38).
  • Relationships diagram (@ChrisJBurns). Folded in from docs: clarify agent definitions, instances, sessions, and runs #2347. Also: the glossary now separates host sessions from broker sessions (c872f08, d830782).
  • Logout (@ChrisJBurns). "Sign out" ends one client's tokens. "Sign out everywhere" stops every agent and schedule. AS-1 re-checks the company-IdP grant, so a disabled account stops acting (5aec36d).
  • Audit (@JAORMX). This covers three changes:
    • an AuditEvent profile, which also has AS-1 set act.iss (1a56af2);
    • delegation lineage kept as retained audit events (905f9e9);
    • delivery, protection, and reconciliation, with the sink being the toolhive-core audit logger pointed at a store mecak8s can't write (3557e50).

Other changes, not asked for in review, worth a look

  • AS-1 ID-JAG flow (e2e684a). The credential flow was reworked around a sign-in at AS-1, a session-bound broker refresh token, and an ID-JAG per call. Its decision record is now folded into the chapters and deleted (f7c5f58).
  • Definition loader (d9fb3c0). It's a broker module again. It loads global definitions at startup, and mecak8s names definitions by reference.
  • ID-JAG §9.3 (ca5d9c1). It's now quoted correctly: the section is about trust domains. Embedded mode is outside its cross-domain scope and reuses the format for one protocol path.
  • Session binding (467060b). At session open, AS-1 now checks that the token's user owns the session, which catches mistakes. Session-bound tokens via RFC 9396 are recorded as later work.
  • Containing a compromised mecak8s (27a5065). The later authority work does this with loader-set ceilings, operator-listed root-eligible definitions, and grants per run.
  • ToolHive ledger. The ToolHive work list in implementation.md is now the ledger of the ToolHive changes this design needs. None is filed as an issue yet.

jhrozek and others added 19 commits October 15, 2026 22:48
Add a Run owner chapter implementing the aligned decision to report the
run owner rather than the session owner. mecak8s sends the run ID and
run owner with every call; the broker checks it against the subject of
the grant in use and never lets it select credentials. Grants, caches,
and vMCP session IDs are keyed by user, revocation is by user, child
runs keep their parent's owner, and audit records the run owner.

Shared sessions can then be added without migrating data or changing
token formats, and should arrive together with run grants. List the
product questions they raise. Replace the sentence that rejected
run-owner attribution.

Co-Authored-By: mecatl <noreply@mecatl.dev>
In deployments that must not lose audit records, every component's
sink must acknowledge only after a durable write; standard output read
by a log shipper does not qualify. Components block or refuse rather
than drop records, so the broker's rule dispatches a tool call only
after its decision record is durably stored. Add the matching check.

Co-Authored-By: mecatl <noreply@mecatl.dev>
ToolHive's ID-JAG redemption enforces an exact subject_bindings list per
issuer, and configuration validation rejects empty lists and wildcard
subjects or resources. AS-2 must redeem for any subject AS-1 names,
resolved through the mapping or consent link. Add the ledger row, with
a note to make it an explicit mode rather than a looser check, and say
so in the gateway administrator's configuration.

Co-Authored-By: mecatl <noreply@mecatl.dev>
The README introduced the loader as its own component before the
identity broker, so it read as a different broker. Introduce the
identity broker first, as the existing MCP broker extended into one
trusted component, and list its modules: the definition loader, the
agent-instance issuer, AS-1, and authorization and audit.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Rewrite the README for readers evaluating Mecatl rather than
implementing it. The opening now states both goals, attributing each
protected call and bounding what an agent may do, with the code-review
example. Correct claims that overstated current behavior (subagent
bounds, audit coverage, the Cedar check, run grants, per-call
exchanges), give the reason behind each design choice, and add
sections on what the design does not guarantee and on the standards it
builds on.

Move root eligibility into the identity work: the broker refuses to
register a root instance whose definition the operator has not made
root-eligible. Ceilings stay in the authority work.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Add threat-model.md with the protections that hold in both
deployments, the full table of what a compromised mecak8s can do in
each, a new row for false reports, the facts mecak8s reports and the
broker's consistency checks on them, and what the split requires. The
README keeps an overview and links to it.

Give the reason for two authorization servers in the gateway modes
chapter, and the full identity-work and authority-work breakdown in the
implementation companion, so the README can shorten without losing
them.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Merge the token flow and the walk through Alice's request into one
end-to-end section that gives the reason for each step, state each
fact once, define ceiling, root, workload, ID-JAG, JWT-SVID, and vMCP
where they are first needed, add a short section on what mecak8s
reports and how the broker checks it, and shorten the order of work and
open questions, linking to the chapters that hold the detail.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Drop the overview's sections on reported facts and non-guarantees; the
threat model, audit, and credentials chapters hold those limits. Shorten
the deployment summary. Explain the two authorization servers through a
gateway Mecatl does not operate, such as the connector gateway in the
Stacklok Enterprise Platform, in the overview and the gateway modes
chapter.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Bring the credentials walkthrough up to date: the diagram now shows the
owner at session open, AS-1's acceptance checks, root eligibility at
registration, the delegation report, the run owner on every call, the
upstream re-check, and step (5). The per-call check list gains the run
owner, and the ceiling check is marked as authority work.

Settle gaps the review found: the broker refresh token does not rotate
and is accepted only for ID-JAG exchanges; a retried session open is
idempotent; the owner and session travel in authorization_details; the
upstream re-check revokes only on invalid_grant; the SVID has one
audience that AS-1 accepts; agent: identifiers are random; single-use
ID-JAGs are Mecatl policy under RFC 7523; schedule authority is its own
record; operation IDs travel in the MCP request _meta. Fix overstated
claims about leaked tokens, AS-1's registry check, and attestation, in
the chapter, the README, and agent-definitions.

Also includes the pending agent-definitions rework: which glossary
terms exist in the code today, how Origin affects ceilings, narrowing
at registration, and why inline MCPServers entries are dropped in
broker mode.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Mermaid treats a semicolon in a sequence-diagram message as a line
break, so four messages added in the previous commit broke the diagram.
Use commas instead, and send the delegation report after the reviewer's
registration reply.

Co-Authored-By: mecatl <noreply@mecatl.dev>
…finitions chapter

- Mark which terms exist in the code today, and correct the claims about Origin, incarnations, child sessions, and instance reuse.
- Narrow authority twice: at registration and at each delegation. The broker keeps a run record and checks it on every protected call.
- List the broker's registration checks, the tier rule for definition ceilings, and how broker mode treats inline MCP servers.
- Have the broker record provenance only for definitions it loaded itself.
- Rewrite the chapter in short, plain sentences.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Rewrite the credential walkthrough so each hop states its input, the
checks in the order they run, what it issues, the error code for each
failure and whether a retry can succeed, why the step exists, what it
does not prove, and what it records. Add the wire bodies for session
open, ID-JAG issuance, and AS-2 redemption, the exact JWT-SVID and
ServiceAccount validation rules, a failure matrix, and renewal triggers.

Apply the round-two review decisions: the upstream re-check
distinguishes revocation from an expired upstream token by its recorded
expiry and refreshes single-flight per user; a retried session open
replaces the first refresh token in one transaction; the session and
owner travel in a mecatl_session authorization_details entry that AS-1
echoes; schedules use mecatl_schedule; act carries a plain ag_
identifier; the run owner is compared with the grant's recorded owner;
a lost redemption re-mints the ID-JAG; and the OAuth sense of trust
domain becomes administrative domain.

Bring the other chapters in line: single-use jti cites RFC 7523,
operation IDs travel in _meta, the AS-1 check lists include the
re-check, and the ToolHive ledger and tests cover the new behavior.

Co-Authored-By: mecatl <noreply@mecatl.dev>
The run owner is the owner recorded with the grant, the company
identity, not AS-1's subject. A child run's owner is reported by
mecak8s and checked against the delegating run's, not copied. The
broker does not admit runs in the identity work: runs and delegations
are reported and recorded as lineage, and delegation ceilings are a
task-specific delegation bound in the authority work.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Apply the third review round across the credential chapters:

- Scheduled runs open their own broker session from the schedule grant,
  so the per-call exchange and cache key are unchanged.
- Refusals that share invalid_request carry a reason code, mapped to a
  broker gRPC status and a mecak8s outcome, including a new
  mcp_owner_action_required outcome.
- The upstream re-check keeps one IdP refresh token per user, refreshes
  under a lease with an in-flight marker, treats invalid_grant after an
  ambiguous refresh as needing owner action, and triggers the broker's
  sign-out-everywhere path on revocation. A revoked grant is never
  revived, whatever its reason.
- A session has one live refresh token, losing it closes the session,
  and closed sessions leave a record so they are never reopened.
- The ID-JAG carries resource; single use is required of embedded AS-2
  and requested of external gateways.
- Quotes of ID-JAG and identity chaining keep the drafts' "trust domain"
  with one gloss.

Also: a delegation report sub-step enforced by the per-call checks,
registration checks the session, exact SVID audience and bundle
selection, retries with fresh client assertions, replay records kept
past the clock skew, a fuller failure matrix, a configuration list, and
the matching tests and ToolHive ledger rows.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Apply the fourth review round:

- Schedule setup and the scheduled-run session open get their own wire
  bodies and checks; a run's session closes when the run ends.
- A user-wide revocation records a revocation time that session open
  and schedule setup enforce, and also revokes every client's refresh
  tokens; sign out everywhere follows one path whoever starts it.
- A revoked grant returns its stored reason, and the broker returns the
  same reason and status when it finds a closed session.
- A later open by the same owner replaces a session's refresh token,
  so an orphaned token can no longer block the session.
- Replacing a session re-registers live instances with their existing
  incarnations and ag_ identifiers, and re-reports open delegations.
- Each run is bound to one instance and owner; a root run needs a root
  instance, and a delegated run the delegation's receiving instance.
- AS-2 returns reason codes; a missing consent link is
  consent_required, the default for external gateways without reasons.
- Reaching the upstream expiry, or an IdP without refresh tokens,
  ends the user's authority with owner_action_required.

Also: the reason-code grammar and full mapping table, session-open
reasons, registration retry rules, failure tables per step, and the
matching tests, record fields, and ledger rows.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Fix what the final review round found:

- A closed session returns its recorded reason with that reason's
  status everywhere; a replaced refresh token returns superseded; a
  lease waiter re-reads its grant before answering.
- Re-registering a SPIFFE ID must match its earlier host session,
  owner, definition revision, and parent; the undefined
  "deregistered" check is dropped.
- Delegation records are kept per session and re-reported parents
  first; an unrecorded delegating run becomes a root run only for a
  root instance.
- Schedule setup keeps the schedule's owner after revocation, renewal
  moves a live grant's horizon, the scheduled-run open refuses a
  closed session and has its own failure table, deleting a schedule
  has its own reason, and scheduled runs map every revocation to
  "needs owner action".
- Sign out everywhere also ends AS-1 login sessions, the revocation
  time compares iat strictly, and issued access tokens are stated to
  keep working for the API until they expire.
- The error_description character set, the README key-sharing and
  instance sentences, the registration list in agent-definitions, and
  stale tests in implementation.md.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Make credentials-and-lifecycle the single home of the end-to-end token
flow and reorder it for implementers:

- One credentials table with custody, then the walkthrough with a new
  step (0) for broker startup, the failure matrix, and error reasons.
- Scheduled runs follow the interactive flow; lifetimes and renewal
  become one table; vMCP sessions move here from the gateway chapter.
- A Later work section collects the unselected options; the workload
  and instance-identity material moves under Reference.
- The User identity, custody, actor-history, provider-selection, and
  sender-binding sections are folded into the steps they belong to.

mcp-gateway-modes keeps only what differs between embedded and
external gateways and links to the flow. implementation.md keeps the
grant record, open items, tests, and ledger, and links to the chapter
instead of restating it. Step numbers are unchanged so existing links
still resolve.

Co-Authored-By: mecatl <noreply@mecatl.dev>
From the pass-3 review:

- Restore the credential record's compare-and-swap refresh, the run
  ID's path to the vMCP, renewal-failure behavior, Mecatl revoking the
  consent link, the broker-side SVID limit, the custody disclaimer,
  RFC 8707 at the vMCP, and the open item on correlation-record order.
- vMCP sessions belong to the instance and user, so they survive a
  replacement broker session and end when the instance ends or the
  user's grants are revoked.
- The delegation report now precedes step (6), which depends on it;
  the failure matrix and error reasons follow scheduled runs, whose
  rows they include; step (0) is marked as a startup prerequisite.
- The embedded-vs-external resolution table lives only in the gateway
  chapter; "provider credential" and "broker refresh token" replace
  the ambiguous "upstream credential" and "session refresh token".
- The chapter points to the tests and the threat model; links to run
  grants and session-bound tokens go to Later work; implementation's
  section is renamed Grant record.
- README: the identity-work checks include the run and its owner, and
  the post-split attacker limit names new sessions and schedule grants.

Co-Authored-By: mecatl <noreply@mecatl.dev>
Replace the "Where trust lives" diagram with one that draws
administrative domains as boxes and the four trust boundaries as
numbered edges: user entry, credential custody between mecak8s and the
broker, gateway entry, and provider egress, each labelled with what
crosses and who checks. It shows the intended deployment, a separate
broker and an external gateway, and a note says what differs today.

The agent trust domain is shown as a naming label on the agents, not a
boundary, since agents share the mecak8s process and their SVIDs are
asserted. AS-1 touches both user entry and gateway entry.

Co-Authored-By: mecatl <noreply@mecatl.dev>

@JAORMX JAORMX left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shipit

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants