59 lines
3.8 KiB
Markdown
59 lines
3.8 KiB
Markdown
# ADR-002: Password accounts and personal agent keys
|
|||
|
|
|
||
|
|
Status: implemented, 14 October 2026.
|
||
|
|
|
||
|
|
Human users sign in with a username/password through `/v1/users/session`. Agent hosts
|
||
|
|
continue to use independent, high-entropy bearer keys. This replaces bearer-key-only
|
||
|
|
human login as the default UI while retaining the existing operator key for initial
|
||
|
|
account setup and recovery. Protected owner review remains a separate password/TOTP,
|
||
|
|
challenge-bound workflow.
|
||
|
|
|
||
|
|
Administrators create and disable accounts with viewer, editor or admin roles and
|
||
|
|
project grants. Editors and administrators issue keys for their own agents at
|
||
|
|
`/v1/me/agent-credentials`; viewers retain read-only access. The server derives the
|
||
|
|
owner from the authenticated account and checks requested grants against current
|
||
|
|
account grants in the same database transaction as issuance. An agent has its own
|
||
|
|
principal identity for proposals/runs. Users can only list and revoke their own keys.
|
||
|
|
Administrators can still inspect and revoke all keys.
|
||
|
|
|
||
|
|
Passwords are hashed with the existing Argon2id implementation. Login uses an
|
||
|
|
HttpOnly, SameSite=Strict session cookie, with Secure on HTTPS. Public password login
|
||
|
|
requires HTTPS; localhost is allowed for development. Browser writes require CSRF
|
||
|
|
and the existing same-origin validation. The development proxy preserves the public
|
||
|
|
Host, allowing TLS-terminating deployments to validate the browser's actual Origin.
|
||
|
|
Forwarded scheme handling remains Uvicorn's trusted-proxy responsibility; application
|
||
|
|
code does not trust arbitrary forwarding headers.
|
||
|
|
|
||
|
|
Five failed logins for a username within 15 minutes block further attempts until
|
||
|
|
that window expires. A shared 100-failure window bounds random-username attempts.
|
||
|
|
Unknown/disabled usernames use a dummy Argon2 verification and generic failure text.
|
||
|
|
This initial limiter favors a small private service; shared lockouts can be abused
|
||
|
|
for denial of service. Larger deployments should add an edge rate limiter.
|
||
|
|
|
||
|
|
Page loads restore existing human browser sessions through `GET /v1/session` with
|
||
|
|
an explicit same-origin client header. The endpoint returns expiry, a CSRF token and
|
||
|
|
account kind; it never returns the session cookie or bearer key. A stable one-way
|
||
|
|
CSRF token is derived from the private session secret and its digest is saved beside
|
||
|
|
the original CSRF digest. This additive migration preserves pre-upgrade sessions and
|
||
|
|
old tabs, while preventing reloads or simultaneous tabs from invalidating each other.
|
||
|
|
Restoration does not extend the original session lifetime. No browser storage is used.
|
||
|
|
|
||
|
|
Changing a password requires the current password, invalidates every browser session
|
||
|
|
for that account, and preserves independent agent keys. Disabling an account revokes
|
||
|
|
its login identity and its agent keys atomically under the canonical authority lock.
|
||
|
|
Activity events include account creation, disable and password changes, without
|
||
|
|
passwords or bearer secrets. Sensitive validation errors omit submitted inputs.
|
||
|
|
|
||
|
|
The strongest alternative is external OIDC/SSO. It avoids local password management
|
||
|
|
but adds an external identity dependency beyond the requested minimal private-service
|
||
|
|
workflow. There is no anonymous registration or email recovery in this slice.
|
||
|
|
|
||
|
|
Migration is additive: `user_accounts`, login failure tracking, and a nullable owner
|
||
|
|
column on credentials. Existing bearer keys and browser sessions continue to work.
|
||
|
|
Account login identities have an unrecoverable random bearer digest; only password
|
||
|
|
sign-in creates their sessions. Rolling back the routes/UI preserves existing keys;
|
||
|
|
new human accounts require the updated identity implementation.
|
||
|
|
|
||
|
|
Validation covers login/CSRF/TLS/body limits, password hashing and changes, session
|
||
|
|
invalidation, user ownership, grant escalation, agent/human separation, disabled users,
|
||
|
|
login throttling, preserved existing credentials, UI setup and personal key issuance.
|