Commit Graph

79 Commits

Author SHA1 Message Date
beubax d54c4159ba fix: avoid audit shutdown deadlock 2026-06-15 14:15:25 +05:30
beubax d4595568ec Merge branch 'main' into feature/stateless-production-deployments 2026-06-12 12:38:32 +05:30
beubax 60e21e1ceb fix: clean redis auth session indexes 2026-06-10 15:58:41 +05:30
beubax 604d18e24a feat: add auth session store contract 2026-06-10 15:54:34 +05:30
beubax 9c50afc585 feat: add global connection fallback registry 2026-06-10 13:57:38 +05:30
Manoj Bajaj ad23d60754 feat: Simplify identity portability 2026-06-05 12:23:32 +05:30
Manoj Bajaj a033bfe93f chore: satisfy pylint ruff checks 2026-06-04 22:22:50 +05:30
Manoj Bajaj 10f6e8ae41 fix: Remove type checking hacks 2026-06-04 21:28:22 +05:30
Manoj Bajaj bfd84b5010 refactor: metadata doesnt need separate file 2026-06-04 19:34:26 +05:30
Manoj Bajaj b96d593883 fix: resolve pre-commit failures 2026-06-04 11:50:56 +05:30
Manoj Bajaj f661d8d360 feature!: Cleaner architechture, multi server compatible identities and cleaner ui 2026-06-03 15:34:55 +05:30
Manoj Bajaj 635285a565 feat: add provider dashboard metadata 2026-06-03 15:17:43 +05:30
Manoj Bajaj 3a6e7e5231 refactor: Simplify server logic for clear reparation, reduce slop
Entire-Checkpoint: 34c348b255f6
2026-05-31 01:41:05 +05:30
beubax c42da7293a refactor: replace audit log file with SQLite-backed audit storage and rename hosted session components to browser sessions 2026-05-29 15:28:47 +05:30
beubax 0bca800339 refactor: reorder import statements and remove unused deployment_mode parameter from route dependencies 2026-05-29 13:52:04 +05:30
Tejas e4a17790f7 Merge branch 'main' into feature/orthogonal-authsome-modules 2026-05-29 13:51:07 +05:30
beubax 7d43b567c8 feat: add principal_role parameter to AuthService and dependency injection routes 2026-05-29 13:30:34 +05:30
Tejas a3e52688ad Merge branch 'main' into feature/orthogonal-authsome-modules 2026-05-29 13:22:28 +05:30
Manoj Bajaj 63bd4c90aa refactor!: unify local and hosted into a single deployment flow
The daemon branched on AUTHSOME_DEPLOYMENT_MODE and ran two parallel
implementations of nearly every ownership concept. "Local and hosted
behave the same" was asserted in prose (ADR 0006) but never enforced in
code, so the paths were free to drift, and the synthetic local principal
let a second local identity silently inherit the admin principal.

Collapse to one flow, identical for every deployment: authsome init
registers an identity and gets back a browser claim URL; the user
registers email+password (first principal becomes admin); that principal
confirms the claim; PoP calls are then authorized.

- Remove AUTHSOME_DEPLOYMENT_MODE, get_deployment_mode(),
  LOCAL_PRINCIPAL_EMAIL, the Local*/Hosted* resolver and bootstrap
  classes, and the AuthService(deployment_mode=...) parameter.
- OwnershipResolver and IdentityBootstrapService become single concrete
  classes (the former hosted, claim-based implementations).
- Admin gating is purely role-based: non-admin principals are blocked in
  every deployment (previously implicitly allowed in local mode).
- The server UI always requires a hosted browser session; remove the
  vestigial HealthResponse.mode field.
- CLI ensure_identity_ready was already mode-agnostic; it now prints the
  claim URL to stderr for headless use.

Add ADR 0007 recording the decision; amend ADR 0006 and CONTEXT.md.

BREAKING CHANGE: existing local installs have an unclaimed identity under
local@authsome.internal and are rejected until the user registers a
principal (email+password) and claims the identity.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entire-Checkpoint: d31cf246f6f2
2026-05-29 13:18:41 +05:30
beubax fbdf580cd6 refactor: introduce CredentialRepository and ProviderRepository to centralize storage and management logic; move functions into their respective domains 2026-05-28 18:30:14 +05:30
Manoj Bajaj 0ed077b9df feat: implement audit events and principal roles
Implement ADR 005 by routing audit events through OpenTelemetry with a server-owned SQLite exporter and query endpoint. Implement ADR 006 by persisting principal roles, assigning first principal admin, and enforcing admin-only routes at the FastAPI dependency layer.

Entire-Checkpoint: df60966364f1
2026-05-28 15:13:56 +05:30
beubax 52c8c2aec6 refactor: simplify create_vault dependency and remove unused server store tests 2026-05-27 16:18:51 +05:30
beubax 5a6c12cd75 Merge branch 'main' into feature/server-store-refactor 2026-05-27 16:06:30 +05:30
beubax 6f0f61c372 refactor: replace file-based registry storage with a unified SQL-backed ServerStore implementation 2026-05-27 16:02:24 +05:30
Tejas 35d0c62ca0 Merge pull request #343 from agentrhq/feature/vault-aes-gcm-dek-kek
feat!: replace flat master-key vault encryption with Argon2id KEK/DEK model
2026-05-27 14:33:26 +05:30
Manoj Bajaj b76903d74b feat: replace flat master-key vault encryption with Argon2id KEK/DEK model
Replaces the flat FernetEncryptionWrapper + EncryptionConfig model with a
proper envelope encryption scheme:

- MasterSecretResolver: unified resolution order (env → file → keyring →
  auto-generate) under a single AUTHSOME_MASTER_KEY env var; no separate
  passphrase vs raw-key distinction — both go through Argon2id
- DekManager: generates a random 256-bit DEK, wraps it with an
  Argon2id-derived KEK (AES-256-GCM), and stores the wrapped record in the
  KV store under __vault_meta__:__dek__ so it works with any KV backend
- AesGcmEncryptionWrapper: drop-in BaseEncryptionWrapper using AES-256-GCM
  per-value encryption via closure; replaces FernetEncryptionWrapper
- Vault: simplified — no longer owns crypto or lifecycle; receives an
  already-encrypted AsyncKeyValue; close() removed (caller manages store)
- EncryptionConfig removed from ServerConfig and models __all__
- Health route updated to report crypto_source from Vault properties
- Tests rewritten with fixtures and SimpleStore (in-memory); no DiskStore

BREAKING CHANGE: existing Fernet-encrypted vaults cannot be read back;
migration requires re-importing credentials.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: a778dfa71075
2026-05-27 14:01:42 +05:30
rishabhraj36 5ea8aa977e fix: added support for cookie expiry date 2026-05-27 13:48:16 +05:30
Manoj Bajaj aeb426357f feat: add browser SSO via Chrome cookie reading (browser-cookie3)
Enables authenticated access to sites like X/Twitter and LinkedIn that
use browser session cookies rather than OAuth or API keys.

Core logic lives entirely in auth/ — BrowserFlow.run_login() reads
Chrome's on-disk SQLite cookie database via browser-cookie3 (macOS
Keychain / Linux GNOME Keyring / Windows DPAPI), opens the site in the
user's default browser if no valid session exists, then polls until the
required auth cookies appear.  No separate Chrome profile, no Playwright.

- auth/browser_cookies.py: read_chrome_cookies(), cookies_are_valid(),
  normalize_jsessionid() with lazy browser-cookie3 import
- auth/flows/browser.py: BrowserFlow (begin/resume/refresh) + static
  run_login() for CLI use
- auth/models/: AuthType.BROWSER, FlowType.BROWSER, BrowserConfig,
  ExtractRule, ConnectionRecord.credentials field
- server/: register flow, header rendering, export branch, BrowserAction
  schema, _session_response wiring (~35 lines total)
- cli/main.py: 8-line elif block calling BrowserFlow.run_login()
- Bundled providers: x-browser, linkedin-browser
- 30 new tests in tests/auth/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 3753e27e5941
2026-05-27 12:27:28 +05:30
beubax 10f17f48e3 fix: rename AUTHSOME_ADMIN_PRINCIPLES environment variable to fix typo 2026-05-25 15:40:57 +05:30
beubax e26d5841f3 feat: enable provider configuration management for hosted admins with required credential inputs and scope persistence 2026-05-25 14:39:04 +05:30
beubax c161ab96d0 feat: implement HostedAccountService for email/password authentication and JWT session management 2026-05-22 18:13:06 +05:30
Manoj Bajaj 3610a69584 refactor: enforce module boundaries — registry impls to server/, AuthService to server/
Phases A–I of TODOS.md:

- Move all five registry classes (IdentityRegistry, PrincipalRegistry,
  VaultRegistry, IdentityClaimRegistry, PrincipalVaultBindingRegistry) from
  identity/ to server/registries.py. Domain model types stay in identity/.

- Break identity/local.py → cli/ coupling: inline _read/_write_active_identity_handle
  helpers so identity/ imports nothing from cli/.

- Remove VaultRegistry + get_server_home imports from auth/service.py; refactor
  revoke() to accept explicit vault_ids from the server layer.

- Move proxy_routes() and _build_route_entry() out of AuthService into
  server/proxy_catalog.py; proxy route delegates to build_proxy_routes().

- Move AuthService from auth/service.py to server/credential_service.py so
  auth/ becomes a true leaf (no vault/, audit/, or server/ imports). Update
  all 10+ import sites in server/, cli/ test files, and the top-level __init__.

- Remove global AuthService(identity="server") from app.py. Refactor /ready
  to resolve the local identity at request time and use app.state.vault directly.

- Remove vault.home property from Vault; replace all callers with store.home.

- Update AGENTS.md architecture table to reflect new file locations.

All 293 tests pass. ruff and ty clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 5c8526a4e7d2
2026-05-20 20:46:17 +05:30
Manoj Bajaj 39c1370ec8 refactor: rename actors package to identity with semantic sub-modules
Replace authsome.actors with authsome.identity, splitting into four
focused sub-modules:
  identity/local.py     — IdentityMetadata, keys, DID helpers, create_identity
  identity/proof.py     — PoP JWT creation and validation
  identity/registry.py  — daemon IdentityRegistry (Handle → DID)
  identity/principal.py — ClaimStatus, PrincipalRegistry, VaultRegistry,
                          IdentityClaimRegistry, PrincipalVaultBindingRegistry

Update all imports across src/ and tests/. Move tests/actors/test_registry.py
to tests/identity/test_registry.py. Delete the actors/ package.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 88222782ec3b
2026-05-20 19:27:13 +05:30
Manoj Bajaj d8553baabb feat: ClaimStatus lifecycle, vault_id gating, ADR 0003 alignment
- Add ClaimStatus enum (PENDING/ACCEPTED/REJECTED) to IdentityClaimRecord
  with accept_claim() and reject_claim() on IdentityClaimRegistry
- HostedOwnershipResolver.resolve() now gates vault access on ACCEPTED;
  PENDING raises 403, REJECTED raises 403 with distinct message
- ensure_claimed_identity() auto-accepts on UI form submission — the form
  IS the approval act in this release; PENDING is transit state only
- Remove AuthService vault_id fallback (vault_id or identity); _coll now
  raises ValueError if vault_id is None, making missing wiring explicit
- /ready endpoint resolves vault_id via ownership_resolver instead of
  constructing AuthService with the identity handle as a stopgap
- create_auth_service() requires explicit vault_id parameter
- Rewrite ADR 0003 and update UBIQUITOUS_LANGUAGE.md to reflect opaque
  VaultId design (single segment, not principal_handle/vault_handle)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 8f56337e3615
2026-05-20 19:26:58 +05:30
beubax 81cd6751df refactor: introduce IdentityStatus enum for identity lifecycle state 2026-05-20 15:33:38 +05:30
beubax 9affa1dc7b refactor: rename scope to vault in key construction utility and storage operations 2026-05-20 15:07:09 +05:30
beubax 923cc93aca feat: scope connections to vault, add claim flow and principal concept, confine UI session to principal view, and make vault/identity/principal orthogonal 2026-05-19 14:25:57 +05:30
Ankit Ranjan da185352b2 refactor: rename provider host_url configuration field to api_url throughout codebase and documentation 2026-05-15 19:01:55 +05:30
beubax 378fa68a42 refactor: replace remote audit logging with local file-based audit and simplify daemon configuration management 2026-05-15 13:53:24 +05:30
beubax 5c98ea5412 refactor: transition to persistent storage backend for sessions, identities, and audit events with async support 2026-05-14 18:04:16 +05:30
beubax be78393d23 feat: make provider client credentials a global property of hosted deployment 2026-05-13 23:22:31 +05:30
beubax 46a981a448 feat: implement local client profile management and update error handling for session authentication 2026-05-13 15:45:04 +05:30
beubax ccc481058e Merge branch 'feature/did-identity-pop-auth' of https://github.com/agentrhq/authsome into feature/did-identity-pop-auth 2026-05-13 14:48:04 +05:30
beubax 79f0a96806 refactor: rename profile to identity 2026-05-13 14:45:51 +05:30
Manoj Bajaj d6958c8434 refactor!: unify Identity and Profile; remove profile management layer
Profile is now a pure credential namespace scoped by the Identity handle,
not an independently managed entity. The two were always 1:1 but modelled
as separate concepts; this commit makes that explicit.

Key changes:
- Add `active_identity` to GlobalConfig; `ensure_local_identity` reads it
  and errors hard if the configured handle is missing on disk (no silent
  re-creation)
- `authsome init` writes `active_identity` to config after registration
- Collapse `registered: bool` + `registration_status: str` on
  IdentityMetadata into a single `registered: bool`; add `mark_registered()`
- Remove vestigial `Identity` dataclass, `DEFAULT_IDENTITY`, `current()`
- Remove `name`, `description`, `owner_email` from IdentityMetadata (deferred
  to hosted version)
- Remove `ProfileMetadata`, `ProfileNotFoundError`, `create_profile`,
  `list_profiles`, `get_profile`, `set_default_profile`, `default_profile`
  shim in save_config — profile is a side-effect of identity registration
- Add hard-error test for missing configured identity
- Update UBIQUITOUS_LANGUAGE.md, AGENTS.md architecture section, and
  ADR 0002 to reflect current code (fix stale AuthsomeContext, AuthClient,
  config.json path, ProfileMetadata references)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 614885258a45
2026-05-13 14:29:18 +05:30
Manoj Bajaj 019bdd11e8 feat!: require server-registered identities
Make the daemon identity registry authoritative for protected PoP requests and remove implicit default-profile identity behavior.

Store daemon-owned state under server/ while keeping CLI signing identity files under identities/.

BREAKING CHANGE: Existing implicit default-profile installs must run authsome init again; profile:default credentials are not migrated.

Entire-Checkpoint: 557455816515
2026-05-12 19:58:43 +05:30
Manoj Bajaj 7ad14f60a3 feat: add did pop daemon authorization
Entire-Checkpoint: a6b771e5077a
2026-05-12 19:18:25 +05:30
beubax 5b2a4fc845 refactor: convert synchronous API route handlers and service methods to asynchronous execution 2026-05-12 15:35:00 +05:30
beubax 32793d38ae refactor: update AuthService test fixture to remove unnecessary mock dependencies 2026-05-12 13:22:29 +05:30
Tejas f6d4ec5184 Merge branch 'main' into fix/warn-when-token-refresh-fails 2026-05-11 13:08:54 +05:30