{"id":47669855,"url":"https://github.com/odysseon/whoami","last_synced_at":"2026-04-14T11:01:02.433Z","repository":{"id":346384150,"uuid":"1189668083","full_name":"odysseon/whoami","owner":"odysseon","description":"Proof of identity without the authorization bloat.","archived":false,"fork":false,"pushed_at":"2026-04-14T01:40:25.000Z","size":730,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-14T02:24:46.480Z","etag":null,"topics":["auth0","authentication"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/odysseon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-23T14:51:22.000Z","updated_at":"2026-04-14T01:40:26.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/odysseon/whoami","commit_stats":null,"previous_names":["odysseon/whoami"],"tags_count":43,"template":false,"template_full_name":null,"purl":"pkg:github/odysseon/whoami","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/odysseon%2Fwhoami","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/odysseon%2Fwhoami/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/odysseon%2Fwhoami/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/odysseon%2Fwhoami/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/odysseon","download_url":"https://codeload.github.com/odysseon/whoami/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/odysseon%2Fwhoami/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31793225,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-14T02:24:21.117Z","status":"ssl_error","status_checked_at":"2026-04-14T02:24:20.627Z","response_time":153,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auth0","authentication"],"created_at":"2026-04-02T12:29:33.101Z","updated_at":"2026-04-14T11:01:02.413Z","avatar_url":"https://github.com/odysseon.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# whoami\n\n**whoami answers one question: who is making this request?**\n\nIt handles identity — registration, authentication (password and OAuth), and signed receipt tokens. It does not manage profiles, roles, or application-level user data. That is intentionally your domain.\n\n## Why this matters\n\nMost auth libraries conflate identity with user management. They force you to extend their `User` model, fight their schema, and work around their assumptions. whoami owns exactly one thing:\n\n```\nAccountId ──► \"This request is from account abc-123. You can trust that.\"\n```\n\nEverything else — what that account can do, what profile they have, what community they belong to — lives in your application, linked by a single foreign key.\n\n## Core value\n\n- **Framework-agnostic core.** Domain logic has zero framework or I/O dependencies. Bring your own NestJS, Express, Fastify, or none.\n- **Adapter-based extensibility.** Swap hashing algorithms, JWT strategies, or frameworks by swapping one package.\n- **Typed identity primitive.** `AccountId` accepts a non-empty `string` — no forced UUID, no silent cast.\n\n## How your entities link to Account\n\nwhoami returns an `AccountId` after authentication. Your application creates its own user record linked by that ID. No base class to extend, no schema to fight.\n\n```\nwhoami DB:\n  accounts  { id, email }                      ← all whoami ever stores\n\nyour DB:\n  users     { id, account_id ← accountId.value, display_name, avatar, ... }\n  posts     { id, author_id  → users.id }\n  channels  { id, owner_id   → users.id }\n```\n\n## Architecture at a glance\n\n```mermaid\ngraph TD\n    subgraph \"Your Application\"\n        YourUser[\"User / Profile / Post / Channel\"]\n        YourController[\"Your Route Handler\"]\n    end\n\n    subgraph \"adapter-nestjs\"\n        Guard[\"WhoamiAuthGuard\"]\n        OAuthHandler[\"OAuthCallbackHandler\"]\n        Decorator[\"@CurrentIdentity()\"]\n    end\n\n    subgraph \"whoami-core — createAuth facade\"\n        AuthMethods[\"AuthMethods facade\\n─────────────────\\nregisterWithPassword\\nauthenticateWithPassword\\nauthenticateWithOAuth\\nlinkOAuthToAccount\\naddPasswordToAccount\\nchangePassword\\ngetAccountAuthMethods\\nremoveAuthMethod\"]\n        IssueUC[\"IssueReceiptUseCase\"]\n        VerifyUC[\"VerifyReceiptUseCase\"]\n        Receipt[\"Receipt { token, accountId, expiresAt }\"]\n    end\n\n    YourController --\u003e Guard\n    Guard --\u003e VerifyUC\n    Decorator --\u003e YourController\n    OAuthHandler --\u003e AuthMethods\n    AuthMethods --\u003e IssueUC\n    IssueUC --\u003e Receipt\n    VerifyUC --\u003e Receipt\n    YourUser -. \"account_id FK\" .-\u003e Receipt\n```\n\n## Packages\n\n| Package | Purpose |\n|---|---|\n| [`@odysseon/whoami-core`](packages/core/README.md) | Domain entities, use cases, port interfaces, and the `createAuth` factory facade |\n| [`@odysseon/whoami-adapter-argon2`](packages/adapter-argon2/README.md) | `PasswordHasher` implementation via argon2 |\n| [`@odysseon/whoami-adapter-jose`](packages/adapter-jose/README.md) | `ReceiptSigner` / `ReceiptVerifier` via jose (HS256 JWT) |\n| [`@odysseon/whoami-adapter-nestjs`](packages/adapter-nestjs/README.md) | NestJS module, OAuth handler, guard, decorator, exception filter |\n\n## Examples\n\n| Example | Framework | What it shows |\n|---|---|---|\n| [`example-nestjs`](packages/example-nestjs/README.md) | NestJS 11 | DI wiring, password + OAuth flows, global guard, Swagger UI |\n| [`example-express`](packages/example-express/README.md) | Express 5 | Minimal wiring, password + OAuth flows, custom auth middleware |\n\n## Quick start\n\n```bash\npnpm install\n\n# run the NestJS example\npnpm --filter @odysseon/whoami-example-nestjs dev\n\n# run the Express example\npnpm --filter @odysseon/whoami-example-express dev\n\n# run all tests\npnpm test\n\n# typecheck all packages\npnpm -r exec tsc --noEmit\n```\n\n## Key docs\n\n| Doc | Purpose |\n|---|---|\n| [docs/architecture.md](docs/architecture.md) | Zone model, dependency rules, module structure |\n| [docs/type-model.md](docs/type-model.md) | AccountId, Receipt, CredentialProof, AuthConfig, error types |\n\n## Development\n\n```bash\npnpm -r exec tsc --noEmit   # typecheck all packages\npnpm test                    # test all packages\n```\n\n## License\n\n[ISC](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fodysseon%2Fwhoami","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fodysseon%2Fwhoami","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fodysseon%2Fwhoami/lists"}