@lssm/module.auth-os
v2.0.2
Published
Reusable AuthOS module with fake adapters and UI flows for identity, authentication, organizations, and Connect with LSSM.
Readme
@lssm/module.auth-os
Reusable AuthOS UI module: a complete atomic-design component library for authentication and
identity flows, composable into any host app or bundle. The module ships atoms → molecules →
organisms → templates → screens in a single package, backed by the AuthOS contract surface
(@lssm/lib.authos-spec) and the AuthObservability port. Production auth execution stays
host-owned; the module provides only the UI and composition layer.
The reusable sign-in surface supports email/password, email OTP, email magic link, and config-driven Google, Microsoft, LinkedIn, TikTok, Facebook, and GitHub buttons. Provider discovery and execution remain host-owned. Web and native hosts can also compose the linked-account panels with their adapter's list/link/unlink operations for providers that require an explicit first link.
Atomic Taxonomy (after Waves 1–4)
| Layer | Count | Location |
| --- | --- | --- |
| Atoms | 16 | src/ui/atoms/ |
| Molecules | 19 | src/ui/molecules/ |
| Organisms | 16 | src/ui/organisms/ |
| Templates | 5 (+1 deprecated alias) | src/ui/templates/ |
| Screens | 12 | src/ui/screens/ |
| Hooks | in progress (Wave 5) | src/ui/hooks/ |
All public exports flow through src/ui/index.ts.
Adapter Contract Surface (AuthOsAdapter)
Defined in
src/ui/hooks/types.ts— landing with Wave 5.
The AuthOsAdapter interface is the boundary between UI hooks and host-supplied auth backends.
Hooks accept an adapter instance and delegate all side-effectful auth operations to it. This
keeps the module free of any bespoke auth engine.
MFA hosts implement a password-gated lifecycle: enrolMfa returns the
authenticator setup URI and one-time recovery codes, confirmMfa verifies the
first TOTP, verifyMfaRecovery consumes a recovery code during sign-in, and
disableMfa re-authenticates before removal. Recovery values remain hook state;
they must never enter logs, observability properties, URLs, or persisted UI
preferences.
i18n Surface
Target locale set: en / fr / es
The readiness target for auth-os is en/fr/es (Option A, decided 2026-06-09).
SUPPORTED_LOCALES = ['en', 'fr', 'es'] in @lssm/lib.contracts-spec/translations.
Atomic catalog structure
Catalogs are split by UI area so parallel workers can fill their own file without
conflicts. All area catalogs share the auth-os.messages spec key.
| Area | Files | Key namespace |
|------|-------|---------------|
| atoms | catalogs/atoms.{en,fr,es}.ts | authOs.atoms.* |
| molecules | catalogs/molecules.{en,fr,es}.ts | authOs.molecules.* |
| organisms | catalogs/organisms.{en,fr,es}.ts | authOs.organisms.* |
| shell | catalogs/shell.{en,fr,es}.ts | authOs.shell.* |
| legacy | catalogs/legacy.{en,fr,es}.ts | auth.* (back-compat) |
Merged catalogs (enMessages / frMessages / esMessages) collapse all areas
into one spec per locale for the runtime registry. The parity gate
(__tests__/catalog-parity.test.ts) enforces identical key sets and placeholder
signatures across en/fr/es for every area — 15 tests, zero failures.
Factory (canonical)
import { createAuthOsI18n } from '@lssm/module.auth-os/i18n';
const i18n = createAuthOsI18n('fr');
i18n.t('authOs.atoms.authCodeInput.defaultLabel'); // → 'Code d\'authentification'Legacy resolver (deprecated back-compat shim)
resolveAuthMessage('auth.<surface>.<key>', params?) — falls back to the key
verbatim when missing; fires AUTH_I18N_MISSING_KEY via the observability port.
New code should use createAuthOsI18n.
German (de) — preserved ungated superset
src/i18n/de.ts is a 297-line legacy monolith retained from before the
atomic area structure. It is:
- NOT gated by
catalog-parity.test.ts(which only gates en/fr/es). - NOT using
defineTranslationor the atomic area shape. - Retained because
de.test.tsgives regression coverage and the translation investment is preserved. - Not to be migrated into
atoms.de/molecules.deetc. unless German becomes a deliberate market commitment.
Usage (legacy resolver only):
import { de } from '@lssm/module.auth-os/i18n';
import { resolveAuthMessage } from '@lssm/module.auth-os/i18n';
const label = resolveAuthMessage('auth.signIn.submit', {}, { catalog: de });
// → 'Anmelden'Subpaths
./i18n · ./i18n/en · ./i18n/resolveAuthMessage
Observability
Port interface and event taxonomy live in src/observability/.
| File | Purpose |
| --- | --- |
| AuthEvent.ts | as const UPPER_SNAKE_CASE enum — 28+ canonical events |
| AuthObservability.ts | Port interface (emit + flush), NoopAuthObservability, ConsoleAuthObservability |
Key events (partial list):
AUTH_SIGN_IN_VIEWED / SUBMITTED / SUCCEEDED / FAILED
AUTH_SIGN_UP_VIEWED / SUBMITTED / SUCCEEDED / FAILED
AUTH_MFA_PROMPTED / FACTOR_SELECTED / VERIFIED / FAILED
AUTH_PASSKEY_REGISTERED / FAILED
AUTH_SESSION_LISTED / REVOKED
AUTH_INVITATION_VIEWED / ACCEPTED / DECLINED
AUTH_AUDIT_VIEWED
AUTH_CONSENT_GRANTED / REVOKEDProps schema (AuthEventProps): enum + numeric + hashed-id only — no PII, no raw tokens, no
i18n strings. The module never imports a concrete analytics SDK (AC-19).
.web / .native Discipline
Platform variants are colocated with their shared base:
atoms/AuthCodeInput/
├── AuthCodeInput.tsx # shared base
├── AuthCodeInput.web.tsx # browser-specific
└── index.ts.web.tsx— browser / Next.js surfaces..native.tsx— React Native / Expo surfaces.- The alias helpers (
withPresentationTurbopackAliases/withPresentationMetroAliases) in@lssm/lib.presentation-runtime-coreroute platform variants at build time.
Bundle Integration
AuthLandingTemplate, PasskeysTemplate, and AccountLockedTemplate from
@lssm/bundle.managed-companyos/ui/templates are locked by the adapter-contract test at
src/__tests__/bundle-adapter-contract.test.tsx via satisfies ComponentProps<typeof T>.
These three templates will be consolidated into the module's own template layer in a follow-up wave; the contract test ensures prop-signature drift is caught at compile time until then.
Status
| Wave | Scope | Status |
| --- | --- | --- |
| 0 | Foundation types + contract test | ✅ Landed |
| 1 | 9 atoms | ✅ Landed |
| 2 | 10 molecules | ✅ Landed |
| 3 | 10 organisms | ✅ Landed |
| 4 | 5 templates + .web/.native pairs | ✅ Landed |
| 5 | 15 hooks + AuthOsAdapter interface | 🔄 In progress |
| 6–7 | Screens refactor + pages + dual-app wiring | ⏳ Deferred |
| 8 | Docs + changeset (this wave) | ✅ Landed |
Automated accessibility qualification
The reusable identity lifecycle now has one automated sweep across all 18 screens: sign-in/up/out, email and magic-link verification, MFA and recovery, passkeys, sessions, security, organization, invitations, and audit. The sweep rejects critical or serious Axe findings, invalid React HTML nesting, and loss of navigation or main landmarks under reduced motion. It is local automated evidence only; manual screen-reader, zoom, contrast, managed-provider, real-device, recovery-drill, and production-canary qualification remain open.
Feature Hub profiles
./hub exposes separate auth-user and auth-admin profiles. The user profile
mounts at /auth with self authority; the admin profile mounts at /admin/auth
with organization authority. Both share the provider-neutral auth.identity
and auth.session ports, while only admin requires auth.authority. Operation
refs are selected from AuthOsOperationRegistry.
Admin effects additionally re-resolve explicit organization authority and a
fresh session for the current tenant/workspace at execution time. A route's
admin metadata, installation success, or a general user session never grants
administrative execution authority by itself.
User routes cover identity, verification, MFA, passkeys, sessions, recovery,
security, and profile. Admin routes separately cover organizations, members,
invitations, roles, sessions, domains, SSO, SCIM, federation, security, and audit.
MFA enrollment contract
AuthOsAdapter.enrolMfa requires { factorKind, password } so credential
accounts re-prove the current password before TOTP setup material is issued.
The result may include an otpauth URI and one-time recovery codes. Consumers
must keep the password, setup URI, and recovery codes in ceremony-local memory,
exclude them from URLs, storage, logs, and telemetry, and call confirmMfa
before presenting MFA as active. Account settings must project the provider's
server-owned enabled state rather than infer it from a completed client step.
Referral and affiliate acquisition
The sign-up view model, hook, form value, and AuthOsAdapter.signUp accept an
optional opaque attributionToken. Hosts may obtain it from GrowthOS URL or
cookie acquisition helpers and bind it into the sign-up screen. AuthOS never
renders the token and excludes it from observability properties.
The deterministic preview adapter consumes the provider bridge's pure bridge-plan entry point. Preview rendering must not import server authentication initialization or database adapters into React Native bundles. Real authentication remains in the injected client adapter.
Published browser conditions select the emitted browser artifacts alongside existing Node/Bun/type targets. Export keys and source behavior are preserved; this packaging metadata does not activate providers or grant execution authority.
