Specs
spec/09-identity-credentials.md · shown exactly as it appears in the repository
09: Agent Access & Credentials
Status: Draft, v0.1.
License: CC-BY-4.0. See LICENSE-DOCS.
Overview
Every other chapter of this spec describes what happens between two parties: establishing a connection, controlling what crosses it, and sharing content over it. This chapter is different: it describes how a single party gets access to their own Bonafide Agent in the first place, before any connection or content exchange is possible. It's deliberately scoped outside the two-layer model: neither a Layer 1 concern (nothing here is visible to, or negotiated with, another party) nor a Layer 2 concern (it's not content, and is never shared).
An implementation MUST treat a credential purely as a local access-control mechanism between a party and their own Agent. A credential MUST NOT be exposed over any connection, appear in any message envelope, or be usable by a router, a peer, or anyone else to correlate one of a party's connections with another. The non-correlation guarantee in 00-overview.md is unaffected by anything in this chapter: a credential exists so a party can reach their own database, not to identify that party to anyone else.
Database isolation
Each party's Bonafide Agent-hosted data (content, connections, subscriptions, and the credentials described below) lives in its own database, isolated from every other party's. An implementation MUST NOT hold more than one party's data in a shared database or table that a single query could span across parties.
This isolation is what makes the "no central identity or accounts" guarantee (00-overview.md) hold in practice, not just at the wire-protocol level: there's no central user table to breach, enumerate, or correlate across parties, only as many independent databases as there are parties.
A credential (below) is stored inside this same isolated database, alongside the party's content. There's no separate, central authentication store. Compromising one party's credential requires compromising that specific party's database; it reveals nothing about any other party's.
Credential records
A credential is the (username, password) pair a party presents to their own Agent to gain access to their database. It's unrelated to, and shares no key material with, the keys a connection generates for itself (02-connections.md). A credential gets a party into their database; it plays no role in anything that happens between parties once they're in.
A credential record is scoped to a single app (see "One credential set per app," below) and is stored, per the isolation requirement above, in the party's own database rather than any datastore shared across parties.
One credential set per app
A single party's database MAY hold more than one credential record, one per app added to that party's account. Each app's credential is independent of every other app's sharing the same database:
- Creating a credential for a new app MUST NOT require or disturb any credential already present for another app.
- Updating or replacing one app's credential (e.g. a password change) MUST NOT delete, invalidate, or otherwise alter any other app's credential record in the same database.
- Removing one app's credential MUST NOT remove another app's.
This is what lets a party use more than one independently developed app against the same underlying account and database.
Password storage
An implementation MUST store a credential's password hashed with a cryptographically appropriate algorithm, salted with a value unique to that credential record. An implementation MUST NOT store or log a credential's password in plaintext, in any form, at any point.
An implementation MUST record, alongside each credential, enough information about the hashing parameters used to produce it (at minimum, the algorithm and work factor/iteration count) to recognize when it was hashed under older parameters. On a successful authentication against an outdated credential, an implementation MUST transparently re-hash the password under current parameters before completing the operation. This is what lets hashing parameters strengthen over time (raising an iteration count, moving to a stronger algorithm) without silently invalidating every credential created before the change.
Provisioning a party's database
Every credential record above presupposes a database for it to live in. Creating that database, and the mechanism by which a party signs up for one, is the responsibility of whatever organization hosts the Agent on the party's behalf: a hosting concern, not a protocol concern. This chapter requires only that a hosting organization provide some mechanism for creating and maintaining a party's database and facilitating signup; it doesn't define what that mechanism looks like.