Architecture
Repository Purpose
@cortexa/auth is a reusable TypeScript library for external OAuth authentication infrastructure in the Cortexa ecosystem.
The repository exists to isolate provider-specific OAuth behavior from consuming applications. It defines common contracts for external auth accounts, sessions, providers, storage, and auth orchestration so applications can connect external accounts, obtain valid access sessions, refresh expired credentials, and disconnect accounts through a consistent in-process API.
This repository is not a standalone authentication service. It does not provide an HTTP server, browser UI, callback routing, first-party user authentication, authorization policy, or production persistence.
Ecosystem Role
The package sits between Cortexa applications and external OAuth providers.
External consumers:
- Node.js and TypeScript applications that import
@cortexa/auth. - Cortexa services that need normalized access to external OAuth accounts and sessions.
- Application-specific storage implementations that conform to the repository's storage contract.
Upstream dependencies:
- External OAuth providers. The implemented provider adapter is Google.
- The
googleapispackage, used by the Google adapter. - Runtime configuration supplied by the host application, including OAuth client credentials and redirect URIs.
Downstream dependencies:
- Consuming applications depend on the exported contracts and service orchestration.
- Provider-specific business integrations may depend on sessions returned by this package, but those integrations are outside this repository.
- Persistent storage backends depend on the storage adapter interface when implemented by consumers.
Related repositories and systems:
- No concrete related repositories are declared in the current repository metadata.
- The package name and description identify this as shared Cortexa auth infrastructure.
- External systems currently include Google OAuth endpoints and Google userinfo access through the Google API client.
Architectural Responsibilities
This repository owns:
- The domain model for external auth accounts, sessions, provider identity, and account lookup.
- The provider contract used to generate auth URLs, exchange authorization codes, refresh sessions, and optionally revoke provider access.
- The storage adapter contract used by the auth orchestration layer.
- A volatile in-memory storage implementation for local, test, or non-production use.
- The
AuthServiceorchestration layer that coordinates provider and storage contracts. - Provider-specific adapter code for Google OAuth.
- Auth-specific error types surfaced to consumers.
- The package public API exported from the library entrypoint.
This repository explicitly delegates:
- OAuth callback routes, request handling, response redirects, and browser interaction to consuming applications.
- First-party user identity, login sessions, cookies, roles, permissions, and authorization policy to other application layers.
- Production database schemas, migrations, transactions, encryption at rest, and account ownership rules to consumer-owned persistence.
- Secret loading, secret rotation, deployment configuration, and environment management to the host runtime.
- Business use of Google APIs or any other provider APIs after a valid session is obtained.
- Cross-service orchestration, queues, schedulers, webhooks, and background workers to other systems.
System Boundaries
Inside the repository boundary:
- TypeScript source for core auth contracts, provider adapters, storage adapters, service orchestration, errors, and examples.
- The npm package API exposed through the source entrypoint.
- Build configuration for emitting JavaScript and TypeScript declaration output.
Outside the repository boundary:
- Any hosted web application or API surface.
- OAuth callback endpoints and redirect handling.
- User account ownership and tenant mapping.
- Persistent storage engines such as SQL, document stores, key-value stores, or secret stores.
- Deployment infrastructure and runtime process management.
- Provider APIs beyond OAuth connection and token lifecycle operations.
Important integration boundaries:
- Consumers pass a concrete
AuthProviderandAuthStorageAdapterintoAuthService. - Consumers own the mapping between external auth accounts and application users or tenants.
- Consumers own secure handling of credentials, tokens, and persisted account records.
- Provider adapters are the only layer that should depend directly on provider SDKs.
High-Level Architecture
The repository follows a small ports-and-adapters structure.
Core domain layer:
- Defines provider names, auth accounts, auth sessions, and account lookup values.
- Contains provider-neutral helpers such as session expiration checks.
- Has no dependency on provider SDKs or storage implementations.
Provider adapter layer:
- Implements provider-specific OAuth behavior behind the common provider contract.
- The implemented adapter is Google.
- Translates provider SDK responses into normalized auth account and session objects.
Storage abstraction layer:
- Defines the persistence contract required by the service layer.
- Includes an in-memory adapter for volatile use cases.
- Leaves durable storage implementation to consumers.
Service orchestration layer:
- Coordinates provider and storage contracts.
- Saves connected accounts, loads accounts, checks session expiration, refreshes sessions, updates stored credentials, and disconnects accounts.
- Remains independent of concrete providers and concrete storage engines.
Public package layer:
- Re-exports the domain contracts, provider implementations, storage contracts, service, and error types consumed by applications.
Domain Overview
The primary domain is external OAuth account connectivity.
Key domain concepts:
- Auth provider: a named external OAuth provider. The implemented provider name is
google. - Auth account: the stored representation of a connected external provider account, including provider identity, provider account ID, access token, optional refresh token, scopes, optional expiration, and optional metadata.
- Auth session: a runtime access session returned to consumers for provider API access.
- Account lookup: the stable provider and provider-account identifier used to retrieve or mutate a connected account.
- Scopes: provider permission strings requested during connection and retained with accounts or sessions.
- Expiration: access sessions may expire and can be refreshed when a refresh token is available through the provider adapter.
The repository models external provider credentials. It does not model application users, tenants, organizations, permissions, or business resources.
Contracts and Integration Points
Public package API:
- Consumers import contracts, providers, storage adapters, services, and errors from the package entrypoint.
- Exported types and classes form the repository's primary integration contract.
Provider contract:
- A provider generates authorization URLs, exchanges authorization codes for accounts, refreshes stored accounts into sessions, and may support revocation.
- Provider implementations normalize provider-specific token responses into repository domain objects.
- Google is the only implemented provider adapter in the current codebase.
Storage contract:
- Storage adapters save, find, update, and delete auth accounts.
- The service layer relies only on the storage contract, not on any concrete database.
- The included memory adapter is volatile and should not be treated as durable production storage.
Service contract:
AuthServiceis the main application-facing orchestration object.- It composes one provider with one storage adapter.
- It raises typed auth errors for missing accounts and provider or configuration failures.
External provider integration:
- Google OAuth is integrated through
googleapis. - Google configuration is supplied explicitly by the consumer.
- Google authorization URL generation, authorization code exchange, and access token refresh are implemented.
- Provider revocation is part of the provider contract, but the current Google revoke behavior is not implemented and must not be treated as working capability.
Infrastructure Responsibilities
Storage and persistence:
- The repository defines the persistence boundary but does not own production persistence.
- Durable storage, schema design, record ownership, transactions, encryption, backup, and retention are consumer responsibilities.
- The in-memory storage adapter is process-local and loses data when the process exits.
Security:
- The repository handles OAuth tokens as data passed between providers, storage adapters, and consumers.
- Consumers are responsible for protecting OAuth client secrets, refresh tokens, access tokens, logs, and persisted account data.
- Consumers must enforce least-privilege scope selection and application-level access control.
Configuration:
- Provider configuration is passed as typed objects.
- The Google provider validates required OAuth configuration values.
- The repository does not own environment loading beyond example usage.
Orchestration:
- All orchestration is in-process library orchestration.
- The repository does not start listeners, schedule background jobs, process queues, or manage deployment infrastructure.
Architectural Constraints and Invariants
- Core domain contracts must remain provider-neutral.
- Provider SDK dependencies must stay behind provider adapter boundaries.
AuthServicemust depend on provider and storage interfaces rather than concrete implementations.- Account identity is based on provider name and provider account ID.
- Storage implementations must preserve enough account data to refresh sessions when provider refresh is required.
- Refresh flows must update stored account credentials before returning the refreshed session to the caller.
- Missing account lookups must surface as typed auth errors rather than provider or storage-specific failures.
- OAuth credentials and tokens must be treated as sensitive data and should not be logged or exposed in documentation examples.
- The memory storage adapter must remain clearly non-durable.
- New providers should be added by implementing the provider contract and keeping provider-specific behavior outside the core domain layer.
- New storage backends should be added by implementing the storage adapter contract without changing service orchestration semantics.
Extensibility and Design Principles
The implemented architecture favors explicit composition over global state. Consumers construct providers and storage adapters, then compose them through the service layer.
The repository uses ports-and-adapters boundaries:
- Provider adapters isolate external OAuth SDK behavior.
- Storage adapters isolate persistence decisions.
- Core contracts remain small and stable.
- The service layer coordinates flows without owning provider or storage implementation details.
The public API is intentionally narrow. Routine additions should preserve existing contracts where possible and add new provider or storage implementations behind the established interfaces.
Errors are represented as auth-specific error classes so consuming applications can distinguish configuration failures, provider failures, and missing account lookups from unrelated runtime errors.
Documentation Corpus Map
Current documentation state:
docs/ARCHITECTURE.md: this document. It is the architectural entrypoint for repository purpose, boundaries, responsibilities, contracts, and design intent.docs/REPOSITORY.md: expected companion document for repository organization, folder structure, package organization, and code placement guidance. It is not present in the current repository at the time this document was generated.README.md: expected repository landing page. It is not present in the current repository at the time this document was generated.
No additional documents were present under docs/ when this architecture document was created.
This document should not duplicate repository navigation material. When docs/REPOSITORY.md exists, use it for folder-level orientation and code placement decisions.
Guidance for Developers and AI Agents
Use this document first to understand architectural boundaries before changing code.
When making changes:
- Identify whether the change belongs to the core domain, provider adapter, storage adapter, service orchestration, or consumer-owned infrastructure.
- Preserve the direction of dependencies: core contracts should not depend on provider SDKs, storage backends, or application infrastructure.
- Treat exported contracts as consumer-facing API.
- Keep production persistence, HTTP routing, user identity, and authorization policy outside this package unless the repository's architectural responsibility is intentionally changed.
- Mark planned or incomplete capabilities explicitly in documentation and code comments; do not describe them as implemented behavior.
- Prefer adding new providers and storage backends through the existing contracts rather than expanding the service layer with provider-specific branches.
For repository organization, folder structure, package organization, and code placement guidance, use docs/REPOSITORY.md once it exists.