Skip to content

docs: a credential spec, and the two designs that answer to it - #199

Open
AliShahin wants to merge 6 commits into
mainfrom
credentials-design
Open

AliShahin wants to merge 6 commits into
mainfrom
credentials-design

Conversation

@AliShahin

@AliShahin AliShahin commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

Three documents: one spec that says what must be true, and two designs that
answer to it.

credential-protection.md (CRED): where credentials come from, which of them
may be held at all, and what a tier binds. Four tiers and three gates, walked
from the top, with each drop recording which condition failed and whether the
counterparty refused or nobody attempted it. It sits apart from labels.md
because the typed credential never becomes a labelled value, so the flow
control has no opinion about one. Twenty-five clauses.

credential-brokering.md: how bravebot gets capabilities that need a secret,
email first, without ever holding one. Extends Brave Vault rather than adding
a second broker. Six phases, 34 tests.

credential-discovery.md: how the credentials already in a working tree are
found before the first turn reads it, shown to the person, and given a
disposition. Built in Brave guardrails, with a rule set vendored from
betterleaks. Eight phases, 30 tests.

The designs divide on capability rather than location: discovery answers
whatever is in the tree, brokering whatever the authority can hold and act
for. The spec is where both stop, since it fixes the tiers they quote and the
gates that decide them.

The argument the spec adds is why the agent is not simply given the secret,
and it is made against safehouse rather than in the abstract. Three of the
properties safehouse's credential gate rests on hold in bravebot too: a label
cannot carry a secret, call parameters are decided from trusted data, and the
key travels in a header the model never sees. The four that fail all reduce to
one thing, which is an open tool surface over a local working tree rather than
typed calls over fetched data. run's parameter is a command line, so there is
no signature to scope a credential to; the content is the person's tree, which
is itself where .env and *.pem live. So the boundary has to sit outside
this process, which is what the brokering design builds.

Limits stated rather than glossed: substitution matches a performer on custody
and not on authority, since the boundary bounds where a request goes and not
which operation it asks for; detection sizes a brief window without setting a
tier; and nothing here is implemented, so twenty-four clauses are
verified-by: none and make check-spec reports them as warnings.

Three places where the code already disagrees with the spec are noted rather
than fixed here, since spec conformance runs in one direction: Secret derives
PartialEq, giving an equality oracle over a credential; the subscription
batch is a plain String under #[derive(Debug)]; and under Bedrock what this
agent authenticates with is the machine's own cloud credentials, which RUN-12
deliberately leaves in a subprocess's environment.

How bravebot gets capabilities that need a secret, email first, without
ever holding one. Extends Brave Vault rather than adding a second broker:
its agent-access plan already states the principles, so the work is
hardening its storage and adding a service-token item type and a perform
action.

Six phases, 34 tests, and three limits stated rather than glossed: the
approval boundary does not hold against a same-uid attacker, encryption
at rest covers a stolen disk only, and none of it retrofits credentials
already on the machine.
…the capability inventory

The ladder moved out to the spec draft and left five references behind
with nothing to resolve against. Restates the four rungs compactly here.

The per-capability inventory went with it, so nothing said what source
control, cloud, payments or protocol servers actually need, or why a card
number is the worst-designed credential an agent could hold.
@AliShahin AliShahin changed the title docs: how bravebot gets credentials without holding them, built on Brave Vault docs: credentials bravebot never holds, and credentials already in the tree Sep 14, 2026
…c's tiers

Renames credentials.md to credential-brokering.md. It pairs with the
discovery design and says what the document decides rather than restating
its subject.

The rung ladder becomes the four named tiers. Two numbering schemes for one
ladder put "rung 1 is best" beside "gate 1 is the first failure", pointing
in opposite directions. The two paths follow: the broker performing an
action whole is Performed rather than Delegated, because substitution
reaches Delegated too, and naming one path after the tier implied the other
did not.

Binds the vocabulary the rest of the work uses: the broker is the authority
and the performer. Neither word appeared in this document before.

Smaller corrections. The tier table's subject is the account, not the
agent, which is the boundary the adversary model turns on. Each row of what
this does not cover says which of the two conditions it fails. The
capability inventory says up front that only email is in scope for the
phases below. Phases 5 and 6 are marked as carrying no tests.
Before the first turn reads a directory, scan it, show what is there, and
let the person answer once. The detector is built in Brave guardrails,
which already intercepts a command's output and needs a checker that
matches rather than one that judges. The rules are vendored from
betterleaks as a pinned file, because patterns change weekly and engines do
not.

Eight phases and 30 tests. Three limits stated rather than glossed: a clean
result is not a clearance, a denied path is a tool-boundary block and not
confinement, and removing a finding does not end the credential.
Where credentials come from, which of them may be held at all, and what a
tier binds: four tiers, three gates, and a walk that records which of the
gate's conditions failed and whether the counterparty refused or nobody
attempted it. Separate from labels.md because the typed credential never
becomes a labelled value, so the flow control has no opinion about one,
which is also the answer to why the agent is not simply given the secret.

Twenty-five clauses. The safehouse comparison is what carries that answer:
three of the properties its credential gate rests on hold here too, and
the four that fail all reduce to an open tool surface over a local tree.
Three limits stated rather than glossed: substitution matches a performer
on custody and not on authority, detection sizes a brief window without
setting a tier, and nothing here is implemented.
@AliShahin AliShahin changed the title docs: credentials bravebot never holds, and credentials already in the tree docs: a credential spec, and the two designs that answer to it Sep 16, 2026
The two paths were described as equivalent because the agent holds nothing
in both. That is true of custody and not of authority: the egress boundary
matches on host, so it bounds where a request goes and never which
operation it asks for. A performer exposes one action; a substituted
credential exposes everything the far end accepts at that destination.

Which gives the rule that decides between them. Substitution is safe where
the issuer bounds the dimension the boundary cannot see. `git push` passes,
because the repository is in the path and a GitHub App token is minted for
one of them. Email fails, because no provider will scope a token to a
recipient, so only something that reads the envelope can bound one.

Adds a diagram for setup and one per message, so the one consent and the
one approval are visible, and a worked example of the substituted path,
which phase 4 did not have. Writing it out found two things the phase has
to settle: a push's credential sits inside a base64 value rather than in a
header, which the position rule does not cover, and the boundary has to
terminate the push's TLS to reach it at all.

Tier rows, lifetimes and two rows of what this does not cover now agree
with the spec rather than restating it loosely. The architecture diagram
no longer draws a child's proxy as a boundary the text calls advice.
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.

1 participant