@owlmeans/client-auth 0.1.18-rc.64 → 0.1.18-rc.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,7 +12,7 @@ legacy). The server-side counterpart is `@owlmeans/server-auth`.
12
12
  ## Installation
13
13
 
14
14
  ```bash
15
- bun add @owlmeans/client-auth@^0.1.18-rc.64
15
+ bun add @owlmeans/client-auth@^0.1.18-rc.66
16
16
  ```
17
17
 
18
18
  ## Concepts
@@ -322,7 +322,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
322
322
  your project's skill store (`.agents/skills/`):
323
323
 
324
324
  ```sh
325
- npx @owlmeans/agent-skills@^0.1.18-rc.56
325
+ npx @owlmeans/agent-skills@^0.1.18-rc.58
326
326
  ```
327
327
 
328
328
  The embedded files are version-matched to this package release. Do not edit them
@@ -1,8 +1,8 @@
1
1
  {
2
- "schemaVersion": 2,
2
+ "schemaVersion": 3,
3
3
  "package": "@owlmeans/client-auth",
4
- "version": "0.1.18-rc.64",
5
- "generatedAt": "2026-10-17T00:00:32.694Z",
4
+ "version": "0.1.18-rc.66",
5
+ "generatedAt": "2026-10-26T16:31:24.895Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -10,7 +10,53 @@
10
10
  "name": "client-auth",
11
11
  "category": "package-specific",
12
12
  "file": "skills/client-auth/SKILL.md",
13
- "canonicalPath": ".agents/skills/client-auth/SKILL.md"
13
+ "canonicalPath": ".agents/skills/client-auth/SKILL.md",
14
+ "parts": [
15
+ {
16
+ "name": "login",
17
+ "file": "skills/client-auth/parts/login.md",
18
+ "description": "The ./login host — method registry, post-login landing, the terms confirmation, surrogate windows, token adoption, and the useLogin/useLogout hooks.",
19
+ "purposes": [
20
+ "auth",
21
+ "consent"
22
+ ],
23
+ "mentions": [
24
+ "useLogin",
25
+ "@owlmeans/client-auth/login",
26
+ "useLogout",
27
+ "appendLogin",
28
+ "loginTermsHelper",
29
+ "loginLandingOf",
30
+ "loginTokenOf",
31
+ "loginStartOf",
32
+ "loginMethodsHelper",
33
+ "LoginStep",
34
+ "LoginPlugin",
35
+ "FallbackLoginScreen"
36
+ ]
37
+ },
38
+ {
39
+ "name": "manager",
40
+ "file": "skills/client-auth/parts/manager.md",
41
+ "description": "The ./manager authentication screen, control and plugin registry, and the ./manager/plugins contract an authentication-plugin package writes against.",
42
+ "purposes": [
43
+ "auth"
44
+ ],
45
+ "mentions": [
46
+ "AuthenticationPlugin",
47
+ "@owlmeans/client-auth/manager",
48
+ "@owlmeans/client-auth/manager/plugins",
49
+ "AuthenticationHOC",
50
+ "AuthenticationRenderer",
51
+ "makeControl",
52
+ "authPluginHelper",
53
+ "registerAuthPlugin",
54
+ "pluginMethodSource",
55
+ "createWalletFacade",
56
+ "TunnelConsumer"
57
+ ]
58
+ }
59
+ ]
14
60
  }
15
61
  ]
16
62
  }
@@ -8,7 +8,7 @@ user-invocable: false
8
8
  # @owlmeans/client-auth
9
9
 
10
10
  **Layer:** Client
11
- **Install:** `"@owlmeans/client-auth": "^0.1.18-rc.64"` in `dependencies`
11
+ **Install:** `"@owlmeans/client-auth": "^0.1.18-rc.66"` in `dependencies`
12
12
 
13
13
  Five subpaths, five jobs:
14
14
 
@@ -48,100 +48,6 @@ conflate them.
48
48
  | `useSelfAuth(force?)` | Whether this context is authenticated; navigates to `DISPATCHER` when it is not and `force` |
49
49
  | `AuthServiceAppend`, `ClientAuthRecord`, `ClientAuthResource` | Types |
50
50
 
51
- ## `./manager` — the authentication screen and the registry
52
-
53
- | Export | Description |
54
- |--------|-------------|
55
- | `plugins`, `authPluginHelper` → `.registerAuthPlugin`, `.getAuthPlugin`, `.listAuthPlugins` | The module-global registry |
56
- | `AuthenticationHOC`, `AuthenticationProps`, `TAuthenticationHOC` | The screen that hosts a plugin's implementation |
57
- | `makeControl`, `AuthenticationControl`, `AuthenticationControlState` | The control a plugin drives: `requestAllowence`, `authenticate`, and the state it persists across a provider redirect |
58
- | `AuthenticationRenderer`, `AuthenticationRendererProps`, `ClientAuthType`, `ClientAuthenticationMethod`, `AuthenticationCallback` | Rendering contract |
59
- | `TunnelConsumer`, `TunnelAuthenticationProps`, `TunnelAuthCallback` | The wallet-tunnel consumer screen |
60
- | `AuthenCredError` | Thrown when the entered credential cannot be used |
61
-
62
- ## `./manager/plugins` — the authentication-plugin contract
63
-
64
- | Export | Description |
65
- |--------|-------------|
66
- | `AuthenticationPlugin` | `type`, `Implementation`, optional `Renderer`, `requiresRenderer?`, `method?` and the `authenticate` / `beforeAuthenticate` / `afterAuthenticate` hooks |
67
- | `PluginImplemnetation` (sic) | `(Renderer?) => FC<AuthenticationRendererProps>` — the shape of `Implementation` |
68
- | `AuthMethodMeta` | How the plugin presents itself as a sign-in method — see `login-methods` |
69
- | `plugins`, `authPluginHelper` | The same registry as `./manager` |
70
- | `pluginMethodSource` | The `LoginMethodSource` that turns registered plugins into offerable methods |
71
- | `createWalletFacade`, `PinSchema`, `PinForm`, `TunnelAuthenticationRenderer`, `TunnelAuthenticationRendererProps` | Wallet-tunnel helpers a consumer plugin builds on |
72
- | `ed25519BasicUIPlugin`, `reCaptchaPlugin`, `tunnelConsumerUIPlugin` | The shipped plugin objects |
73
-
74
- Shipped plugins register themselves by side effect: `basic-ed25519`, `re-captcha` and
75
- `wallet-consumer` when `@owlmeans/client-auth/manager` is imported, OIDC and Google from
76
- `@owlmeans/web-oidc-rp/auth/plugins`, the PK supervisor from `@owlmeans/web-auth`.
77
-
78
- ## `./login` — the login-plugin host
79
-
80
- An `AuthenticationPlugin` answers how a credential is proven; a `LoginPlugin` answers in which
81
- browsing context the round trip can complete at all.
82
-
83
- | Export | Description |
84
- |--------|-------------|
85
- | `appendLogin(ctx)` | Register the host and expose it as `context.login()` |
86
- | `makeLoginService(alias?)`, `ensureLoginService(ctx)` | The host itself — a **lazy** service, so `makeContext` can reach it at the Loading stage — and the idempotent getter a plugin package calls before `registerPlugin` |
87
- | `LoginPlugin`, `LoginEnv`, `LoginRequest`, `LogoutRequest`, `LoginOutcome`, `LoginIntent`, `LoginService`, `LoginContext`, `LoginPrecondition` | The contract |
88
- | `loginMethodsHelper` → `.registerMethodSource`, `.listMethodSources`, `.resolveLoginMethods`, `.primaryLoginMethod` | Which sign-in methods are offered — see `login-methods` |
89
- | `LoginMethod`, `LoginMethodSource`, `LoginMethodContext` | Method types |
90
- | `loginLandingOf(ctx)` → `.landAfterLogin(opts?)`, `.continueLogin(opts?)`, `.landingUrl(landing)`; `useContinueLogin()` | The post-login landing decision (`src/login/land.ts`) — see `login-plugins`. `landAfterLogin` runs due landing hooks then delegates to `continueLogin`, which walks pending `LoginStep`s, then `flowLandingOf(ctx).resumeSuspendedFlow`, then `LandOptions.fallback ?? { alias: HOME }`; `landingUrl` builds the absolute URL a plugin's own `window.location.href` needs; `useContinueLogin()` is what a step's own screen calls once satisfied |
91
- | `LoginStep`, `LoginLanding`, `LoginLandingHook`, `LandOptions`, `LoginLandingParams` | Landing-seam types. `registerStep`/`steps`/`onLanded`/`landingHooks` on `LoginService` are the same replace-by-alias, priority-sorted registries as `registerPlugin`. `LoginStep` also carries `confirmsTerms?: boolean` (this step is where the Terms confirmation lives — see `loginTermsHelper.termsDeferred` below) and `required?: boolean` (a throw/timeout in `pending` reads as PENDING, not "not pending" — see `login-plugins`) |
92
- | `LOGIN_STEP_TIMEOUT`, `LOGIN_LANDED_STORAGE` | A step's `pending`/a hook's `landed` is bounded by the former; the latter is where the last-landed token is recorded (the raw string, never a digest) |
93
- | `loginTermsHelper` → `.resolveTerms`, `.termsAccepted`, `.acceptTerms`, `.termsSentence`, `ResolvedTerms`, `ResolvedTermsDocument`, `TermsSentencePart` | The confirmation. `resolveTerms` produces `documents` (what the checkbox agrees to: terms, then billing/product/custom when configured) and `notices` (what is only disclosed: privacy, plus cookies per its own inclusion rule) — see the terms-confirmation section of `login-methods`. The extra `LoginTermsConfig` fields (`billing`, `product`, `documents`, `revisions`, `showRevision`, `localizedHrefs`) are added by module augmentation in `src/login/terms-config.ts`, never by editing `@owlmeans/config` — importing anything from `@owlmeans/client-auth/login` pulls it in |
94
- | `loginTermsHelper.termsLabelResolver(translate, locale)`, `loginTermsHelper.termsAcceptanceOf(resolved, locale?)`, `TermsAcceptanceRef` | The ONE document-label resolver and ONE wire-shape builder every terms renderer/recorder shares (`FallbackLoginScreen`, `web-panel`'s `LoginTerms`, `web-marketing-consent`'s Terms box and `termsRecorder`) — no more hand-kept duplicate `DEFAULT_LABEL`/`resolveLabelFor` per package. `termsAcceptanceOf` keeps only `{key, href, revisedAt}` per document — structurally `@owlmeans/marketing-consent`'s `TermsAcceptance`, with no dependency on that package |
95
- | `loginTermsHelper.termsDeferred(ctx)` | True once a registered AND BOUND `LoginStep` declares `confirmsTerms` — see the "Deferring the confirmation" section of `login-methods`. Reads `ctx.hasService`/`.hasEntrypoint` directly, never `ensureLoginService` (which has the side effect of registering an empty host) |
96
- | `resolveCredit`, `ResolvedCredit` | The credit and copyright line |
97
- | `FallbackLoginScreen`, `LoginScreenProps` (now also carries `locale?: string`, for `Intl.ListFormat` and a custom document's locale-keyed label), `LoginScreenComponent` | The plain sign-in screen a relying party renders when no UI family registered one |
98
- | `surrogatePath(ctx, target)`, `SurrogateTarget` | Where a surrogate login window opens; `null` on an older entrypoint list |
99
- | `loginResumeHelper.resumeAction(outcome)`, `ResumeAction`, `loginResumeHelper.loginAttemptError(outcome)` | The one reading of a `resume` outcome, and the one reading of a finished attempt |
100
- | `registerNotifier(notifier)` (on `LoginService`), `LoginNotifier` | Surfaces a `begin`/`logout` outcome that has no inline screen to render it on — e.g. a toast on `LoginOutcome.Blocked` for a header "Log in"/"Log out" control. `web-panel`'s `appendLoginScreen` registers a default; unregistered, it is silence |
101
- | `enterOidcAuthorization(model)` | Move a flow to the step that can authorize — idempotent, call it before every `authenticate` |
102
- | `loginTokenOf(ctx).adoptToken(token)`, `.revokeToken()` | The single adoption and de-adoption paths |
103
- | `useLogin(target?)`, `useLogout(target?)` | Wiring for a sign-in / sign-out control. `useLogin`'s `target` is the screen to land on AFTER sign-in (parked, never navigated to first); `useLogout`'s is where the document goes once the session is gone |
104
- | `loginStartOf(ctx).startLogin({ url, target?, go })`, `LoginStart` | The React-free decision behind `useLogin` (`src/login/start.ts`): a target with a session already held goes straight there; otherwise `begin` with the target and a continuation to `DISPATCHER` |
105
- | `loginEnvHelper` → `.isEmbedded`, `.isSurrogate`, `.markSurrogate`, `.clearSurrogate`, `.defaultLoginEnv` | Environment probes the host builds `LoginEnv` from |
106
- | `LOGIN_SERVICE`, `LOGIN_SURROGATE_NAME`, `LOGIN_TOKEN_MESSAGE`, `LOGIN_LOGOUT_MESSAGE`, `LOGIN_SURROGATE_MARKER`, `LOGIN_SURROGATE_WIDTH`, `LOGIN_SURROGATE_HEIGHT`, `LOGIN_WATCH_INTERVAL`, `LOGIN_INTENT_QUERY`, `LOGIN_NEXT_QUERY`, `LOGIN_METHOD_QUERY`, `LOGIN_TERMS_STORAGE`, `LOGIN_TARGET_TTL`, `DEFAULT_LOGIN_PRIORITY`, `DEFAULT_METHOD_ORDER` | Aliases and the fixed cross-document wire values. `LOGIN_SURROGATE_FEATURES` also still exports (deprecated, never centered) — `@owlmeans/web-client`'s `centeredPopupFeatures(LOGIN_SURROGATE_WIDTH, LOGIN_SURROGATE_HEIGHT)` is what the surrogate plugin actually opens the window with |
107
-
108
- ```typescript
109
- import { useLogin, useLogout } from '@owlmeans/client-auth/login'
110
-
111
- const [loginPath, onLogIn] = useLogin()
112
- const onLogOut = useLogout()
113
- ```
114
-
115
- Both handlers are deliberately **not** async and await nothing before delegating — a window opened
116
- after the user gesture has finished being handled is eaten by the popup blocker. Each resolves its
117
- entrypoint **inside** the hook, never at module scope — `DISPATCHER` for `useLogin`, the surrogate
118
- path for `useLogout`. A module body runs before `registerEntrypoints`, so `useLogin`'s lookup at
119
- top level throws `Entrypoint dispatcher not found` during import, taking the whole render down.
120
-
121
- `useLogin(target)` signs in FIRST and lands on `target` after, in an ordinary tab (redirect plugin)
122
- and in a framed application (surrogate popup) alike, with every pending post-sign-in step run on the
123
- way. Its `navigate` continuation is ALWAYS `DISPATCHER` — never the target, because a guarded screen
124
- reached before sign-in renders signed out. The target travels as `LoginRequest.target`: the facade's
125
- `begin`, past the preconditions, parks it with `flowLandingOf(ctx).suspendLanding`
126
- (`@owlmeans/client-flow`, the `RESUME_FLOW` record its `resumeSuspendedFlow` reads, expiring after
127
- `LOGIN_TARGET_TTL`) — the write is started, never awaited before the plugin, so a popup still opens
128
- inside the gesture — and holds the continuation until the write has landed. The dispatcher's
129
- `landAfterLogin` (landing hooks → pending steps such as a consent screen → the parked target) then
130
- ends on it. An attempt that signs nobody in (`Blocked`, `Failed`, `Gesture`) discards the parked
131
- target; a refused precondition never parks it. A session already held (the auth service's in-memory
132
- `token`) goes straight to the target. Without a target, `useLogin()` is the plain sign-in to the
133
- ordinary landing. A caller of `login().begin` that passes a `target` without a `navigate` leaves the
134
- document at once, so its parked target is best-effort.
135
-
136
- `useLogout` sends a continuation only when a target is given. Omitting it does not leave the session
137
- behind: the token is revoked either way, and the plugin decides what the document does with no
138
- continuation to run — `@owlmeans/web-client`'s redirect plugin reloads the page, because cached auth
139
- reads only forget a session when the application is rebuilt. `useLogin` returns `[path, handler]`
140
- (the path is the dispatcher's, with or without a target) and `useLogout` a bare handler — a logout
141
- control has no address to point at.
142
-
143
- Plugin selection, the shipped browser flows and the full invariant list: the `login-plugins` skill.
144
-
145
51
  ## Usage
146
52
 
147
53
  ```typescript
@@ -195,3 +101,10 @@ a web application only calls these when it builds its context by hand.
195
101
  - `@owlmeans/basic-envelope` — decoding the bearer envelope
196
102
  - `react` (peer)
197
103
  - `ajv` (peer) — `PinSchema` is typed as `JSONSchemaType<PinForm>`
104
+
105
+ ## Parts
106
+
107
+ | Part | Load it when |
108
+ |---|---|
109
+ | [manager](parts/manager.md) | registering or writing an authentication plugin, or rendering the authentication screen |
110
+ | [login](parts/login.md) | wiring a sign-in or sign-out control, a login step, the terms confirmation, or the post-login landing |
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: login
3
+ description: The ./login host — method registry, post-login landing, the terms confirmation, surrogate windows, token adoption, and the useLogin/useLogout hooks.
4
+ metadata:
5
+ purposes: auth, consent
6
+ mentions: useLogin, @owlmeans/client-auth/login, useLogout, appendLogin, loginTermsHelper, loginLandingOf, loginTokenOf, loginStartOf, loginMethodsHelper, LoginStep, LoginPlugin, FallbackLoginScreen
7
+ ---
8
+ <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
9
+
10
+ # @owlmeans/client-auth — The login-plugin host
11
+
12
+ ## `./login` — the login-plugin host
13
+
14
+ An `AuthenticationPlugin` answers how a credential is proven; a `LoginPlugin` answers in which
15
+ browsing context the round trip can complete at all.
16
+
17
+ | Export | Description |
18
+ |--------|-------------|
19
+ | `appendLogin(ctx)` | Register the host and expose it as `context.login()` |
20
+ | `makeLoginService(alias?)`, `ensureLoginService(ctx)` | The host itself — a **lazy** service, so `makeContext` can reach it at the Loading stage — and the idempotent getter a plugin package calls before `registerPlugin` |
21
+ | `LoginPlugin`, `LoginEnv`, `LoginRequest`, `LogoutRequest`, `LoginOutcome`, `LoginIntent`, `LoginService`, `LoginContext`, `LoginPrecondition` | The contract |
22
+ | `loginMethodsHelper` → `.registerMethodSource`, `.listMethodSources`, `.resolveLoginMethods`, `.primaryLoginMethod` | Which sign-in methods are offered — see `login-methods` |
23
+ | `LoginMethod`, `LoginMethodSource`, `LoginMethodContext` | Method types |
24
+ | `loginLandingOf(ctx)` → `.landAfterLogin(opts?)`, `.continueLogin(opts?)`, `.landingUrl(landing)`; `useContinueLogin()` | The post-login landing decision (`src/login/land.ts`) — see `login-plugins`. `landAfterLogin` runs due landing hooks then delegates to `continueLogin`, which walks pending `LoginStep`s, then `flowLandingOf(ctx).resumeSuspendedFlow`, then `LandOptions.fallback ?? { alias: HOME }`; `landingUrl` builds the absolute URL a plugin's own `window.location.href` needs; `useContinueLogin()` is what a step's own screen calls once satisfied |
25
+ | `LoginStep`, `LoginLanding`, `LoginLandingHook`, `LandOptions`, `LoginLandingParams` | Landing-seam types. `registerStep`/`steps`/`onLanded`/`landingHooks` on `LoginService` are the same replace-by-alias, priority-sorted registries as `registerPlugin`. `LoginStep` also carries `confirmsTerms?: boolean` (this step is where the Terms confirmation lives — see `loginTermsHelper.termsDeferred` below) and `required?: boolean` (a throw/timeout in `pending` reads as PENDING, not "not pending" — see `login-plugins`) |
26
+ | `LOGIN_STEP_TIMEOUT`, `LOGIN_LANDED_STORAGE` | A step's `pending`/a hook's `landed` is bounded by the former; the latter is where the last-landed token is recorded (the raw string, never a digest) |
27
+ | `loginTermsHelper` → `.resolveTerms`, `.termsAccepted`, `.acceptTerms`, `.termsSentence`, `ResolvedTerms`, `ResolvedTermsDocument`, `TermsSentencePart` | The confirmation. `resolveTerms` produces `documents` (what the checkbox agrees to: terms, then billing/product/custom when configured) and `notices` (what is only disclosed: privacy, plus cookies per its own inclusion rule) — see the terms-confirmation section of `login-methods`. The extra `LoginTermsConfig` fields (`billing`, `product`, `documents`, `revisions`, `showRevision`, `localizedHrefs`) are added by module augmentation in `src/login/terms-config.ts`, never by editing `@owlmeans/config` — importing anything from `@owlmeans/client-auth/login` pulls it in |
28
+ | `loginTermsHelper.termsLabelResolver(translate, locale)`, `loginTermsHelper.termsAcceptanceOf(resolved, locale?)`, `TermsAcceptanceRef` | The ONE document-label resolver and ONE wire-shape builder every terms renderer/recorder shares (`FallbackLoginScreen`, `web-panel`'s `LoginTerms`, `web-marketing-consent`'s Terms box and `termsRecorder`) — no more hand-kept duplicate `DEFAULT_LABEL`/`resolveLabelFor` per package. `termsAcceptanceOf` keeps only `{key, href, revisedAt}` per document — structurally `@owlmeans/marketing-consent`'s `TermsAcceptance`, with no dependency on that package |
29
+ | `loginTermsHelper.termsDeferred(ctx)` | True once a registered AND BOUND `LoginStep` declares `confirmsTerms` — see the "Deferring the confirmation" section of `login-methods`. Reads `ctx.hasService`/`.hasEntrypoint` directly, never `ensureLoginService` (which has the side effect of registering an empty host) |
30
+ | `resolveCredit`, `ResolvedCredit` | The credit and copyright line |
31
+ | `FallbackLoginScreen`, `LoginScreenProps` (now also carries `locale?: string`, for `Intl.ListFormat` and a custom document's locale-keyed label), `LoginScreenComponent` | The plain sign-in screen a relying party renders when no UI family registered one |
32
+ | `surrogatePath(ctx, target)`, `SurrogateTarget` | Where a surrogate login window opens; `null` on an older entrypoint list |
33
+ | `loginResumeHelper.resumeAction(outcome)`, `ResumeAction`, `loginResumeHelper.loginAttemptError(outcome)` | The one reading of a `resume` outcome, and the one reading of a finished attempt |
34
+ | `registerNotifier(notifier)` (on `LoginService`), `LoginNotifier` | Surfaces a `begin`/`logout` outcome that has no inline screen to render it on — e.g. a toast on `LoginOutcome.Blocked` for a header "Log in"/"Log out" control. `web-panel`'s `appendLoginScreen` registers a default; unregistered, it is silence |
35
+ | `enterOidcAuthorization(model)` | Move a flow to the step that can authorize — idempotent, call it before every `authenticate` |
36
+ | `loginTokenOf(ctx).adoptToken(token)`, `.revokeToken()` | The single adoption and de-adoption paths |
37
+ | `useLogin(target?)`, `useLogout(target?)` | Wiring for a sign-in / sign-out control. `useLogin`'s `target` is the screen to land on AFTER sign-in (parked, never navigated to first); `useLogout`'s is where the document goes once the session is gone |
38
+ | `loginStartOf(ctx).startLogin({ url, target?, go })`, `LoginStart` | The React-free decision behind `useLogin` (`src/login/start.ts`): a target with a session already held goes straight there; otherwise `begin` with the target and a continuation to `DISPATCHER` |
39
+ | `loginEnvHelper` → `.isEmbedded`, `.isSurrogate`, `.markSurrogate`, `.clearSurrogate`, `.defaultLoginEnv` | Environment probes the host builds `LoginEnv` from |
40
+ | `LOGIN_SERVICE`, `LOGIN_SURROGATE_NAME`, `LOGIN_TOKEN_MESSAGE`, `LOGIN_LOGOUT_MESSAGE`, `LOGIN_SURROGATE_MARKER`, `LOGIN_SURROGATE_WIDTH`, `LOGIN_SURROGATE_HEIGHT`, `LOGIN_WATCH_INTERVAL`, `LOGIN_INTENT_QUERY`, `LOGIN_NEXT_QUERY`, `LOGIN_METHOD_QUERY`, `LOGIN_TERMS_STORAGE`, `LOGIN_TARGET_TTL`, `DEFAULT_LOGIN_PRIORITY`, `DEFAULT_METHOD_ORDER` | Aliases and the fixed cross-document wire values. `LOGIN_SURROGATE_FEATURES` also still exports (deprecated, never centered) — `@owlmeans/web-client`'s `centeredPopupFeatures(LOGIN_SURROGATE_WIDTH, LOGIN_SURROGATE_HEIGHT)` is what the surrogate plugin actually opens the window with |
41
+
42
+ ```typescript
43
+ import { useLogin, useLogout } from '@owlmeans/client-auth/login'
44
+
45
+ const [loginPath, onLogIn] = useLogin()
46
+ const onLogOut = useLogout()
47
+ ```
48
+
49
+ Both handlers are deliberately **not** async and await nothing before delegating — a window opened
50
+ after the user gesture has finished being handled is eaten by the popup blocker. Each resolves its
51
+ entrypoint **inside** the hook, never at module scope — `DISPATCHER` for `useLogin`, the surrogate
52
+ path for `useLogout`. A module body runs before `registerEntrypoints`, so `useLogin`'s lookup at
53
+ top level throws `Entrypoint dispatcher not found` during import, taking the whole render down.
54
+
55
+ `useLogin(target)` signs in FIRST and lands on `target` after, in an ordinary tab (redirect plugin)
56
+ and in a framed application (surrogate popup) alike, with every pending post-sign-in step run on the
57
+ way. Its `navigate` continuation is ALWAYS `DISPATCHER` — never the target, because a guarded screen
58
+ reached before sign-in renders signed out. The target travels as `LoginRequest.target`: the facade's
59
+ `begin`, past the preconditions, parks it with `flowLandingOf(ctx).suspendLanding`
60
+ (`@owlmeans/client-flow`, the `RESUME_FLOW` record its `resumeSuspendedFlow` reads, expiring after
61
+ `LOGIN_TARGET_TTL`) — the write is started, never awaited before the plugin, so a popup still opens
62
+ inside the gesture — and holds the continuation until the write has landed. The dispatcher's
63
+ `landAfterLogin` (landing hooks → pending steps such as a consent screen → the parked target) then
64
+ ends on it. An attempt that signs nobody in (`Blocked`, `Failed`, `Gesture`) discards the parked
65
+ target; a refused precondition never parks it. A session already held (the auth service's in-memory
66
+ `token`) goes straight to the target. Without a target, `useLogin()` is the plain sign-in to the
67
+ ordinary landing. A caller of `login().begin` that passes a `target` without a `navigate` leaves the
68
+ document at once, so its parked target is best-effort.
69
+
70
+ `useLogout` sends a continuation only when a target is given. Omitting it does not leave the session
71
+ behind: the token is revoked either way, and the plugin decides what the document does with no
72
+ continuation to run — `@owlmeans/web-client`'s redirect plugin reloads the page, because cached auth
73
+ reads only forget a session when the application is rebuilt. `useLogin` returns `[path, handler]`
74
+ (the path is the dispatcher's, with or without a target) and `useLogout` a bare handler — a logout
75
+ control has no address to point at.
76
+
77
+ Plugin selection, the shipped browser flows and the full invariant list: the `login-plugins` skill.
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: manager
3
+ description: The ./manager authentication screen, control and plugin registry, and the ./manager/plugins contract an authentication-plugin package writes against.
4
+ metadata:
5
+ purposes: auth
6
+ mentions: AuthenticationPlugin, @owlmeans/client-auth/manager, @owlmeans/client-auth/manager/plugins, AuthenticationHOC, AuthenticationRenderer, makeControl, authPluginHelper, registerAuthPlugin, pluginMethodSource, createWalletFacade, TunnelConsumer
7
+ ---
8
+ <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
9
+
10
+ # @owlmeans/client-auth — The authentication screen and plugin contract
11
+
12
+ ## `./manager` — the authentication screen and the registry
13
+
14
+ | Export | Description |
15
+ |--------|-------------|
16
+ | `plugins`, `authPluginHelper` → `.registerAuthPlugin`, `.getAuthPlugin`, `.listAuthPlugins` | The module-global registry |
17
+ | `AuthenticationHOC`, `AuthenticationProps`, `TAuthenticationHOC` | The screen that hosts a plugin's implementation |
18
+ | `makeControl`, `AuthenticationControl`, `AuthenticationControlState` | The control a plugin drives: `requestAllowence`, `authenticate`, and the state it persists across a provider redirect |
19
+ | `AuthenticationRenderer`, `AuthenticationRendererProps`, `ClientAuthType`, `ClientAuthenticationMethod`, `AuthenticationCallback` | Rendering contract |
20
+ | `TunnelConsumer`, `TunnelAuthenticationProps`, `TunnelAuthCallback` | The wallet-tunnel consumer screen |
21
+ | `AuthenCredError` | Thrown when the entered credential cannot be used |
22
+
23
+ ## `./manager/plugins` — the authentication-plugin contract
24
+
25
+ | Export | Description |
26
+ |--------|-------------|
27
+ | `AuthenticationPlugin` | `type`, `Implementation`, optional `Renderer`, `requiresRenderer?`, `method?` and the `authenticate` / `beforeAuthenticate` / `afterAuthenticate` hooks |
28
+ | `PluginImplemnetation` (sic) | `(Renderer?) => FC<AuthenticationRendererProps>` — the shape of `Implementation` |
29
+ | `AuthMethodMeta` | How the plugin presents itself as a sign-in method — see `login-methods` |
30
+ | `plugins`, `authPluginHelper` | The same registry as `./manager` |
31
+ | `pluginMethodSource` | The `LoginMethodSource` that turns registered plugins into offerable methods |
32
+ | `createWalletFacade`, `PinSchema`, `PinForm`, `TunnelAuthenticationRenderer`, `TunnelAuthenticationRendererProps` | Wallet-tunnel helpers a consumer plugin builds on |
33
+ | `ed25519BasicUIPlugin`, `reCaptchaPlugin`, `tunnelConsumerUIPlugin` | The shipped plugin objects |
34
+
35
+ Shipped plugins register themselves by side effect: `basic-ed25519`, `re-captcha` and
36
+ `wallet-consumer` when `@owlmeans/client-auth/manager` is imported, OIDC and Google from
37
+ `@owlmeans/web-oidc-rp/auth/plugins`, the PK supervisor from `@owlmeans/web-auth`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/client-auth",
3
- "version": "0.1.18-rc.64",
3
+ "version": "0.1.18-rc.66",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -50,27 +50,27 @@
50
50
  }
51
51
  },
52
52
  "dependencies": {
53
- "@owlmeans/auth": "^0.1.18-rc.41",
54
- "@owlmeans/auth-common": "^0.1.18-rc.51",
55
- "@owlmeans/basic-envelope": "^0.1.18-rc.50",
56
- "@owlmeans/basic-keys": "^0.1.18-rc.52",
57
- "@owlmeans/client": "^0.1.18-rc.56",
58
- "@owlmeans/client-context": "^0.1.18-rc.52",
59
- "@owlmeans/client-entrypoint": "^0.1.18-rc.51",
60
- "@owlmeans/client-flow": "^0.1.18-rc.59",
61
- "@owlmeans/client-resource": "^0.1.18-rc.51",
62
- "@owlmeans/client-socket": "^0.1.18-rc.55",
63
- "@owlmeans/config": "^0.1.18-rc.44",
64
- "@owlmeans/context": "^0.1.18-rc.34",
65
- "@owlmeans/did": "^0.1.18-rc.51",
66
- "@owlmeans/entrypoint": "^0.1.18-rc.41",
67
- "@owlmeans/error": "^0.1.18-rc.38",
68
- "@owlmeans/flow": "^0.1.18-rc.45",
69
- "@owlmeans/i18n": "^0.1.18-rc.39",
70
- "@owlmeans/log": "^0.1.18-rc.3",
71
- "@owlmeans/resource": "^0.1.18-rc.40",
72
- "@owlmeans/socket": "^0.1.18-rc.44",
73
- "@owlmeans/web-flow": "^0.1.18-rc.58",
53
+ "@owlmeans/auth": "^0.1.18-rc.42",
54
+ "@owlmeans/auth-common": "^0.1.18-rc.53",
55
+ "@owlmeans/basic-envelope": "^0.1.18-rc.52",
56
+ "@owlmeans/basic-keys": "^0.1.18-rc.54",
57
+ "@owlmeans/client": "^0.1.18-rc.58",
58
+ "@owlmeans/client-context": "^0.1.18-rc.54",
59
+ "@owlmeans/client-entrypoint": "^0.1.18-rc.53",
60
+ "@owlmeans/client-flow": "^0.1.18-rc.61",
61
+ "@owlmeans/client-resource": "^0.1.18-rc.53",
62
+ "@owlmeans/client-socket": "^0.1.18-rc.57",
63
+ "@owlmeans/config": "^0.1.18-rc.45",
64
+ "@owlmeans/context": "^0.1.18-rc.35",
65
+ "@owlmeans/did": "^0.1.18-rc.53",
66
+ "@owlmeans/entrypoint": "^0.1.18-rc.42",
67
+ "@owlmeans/error": "^0.1.18-rc.39",
68
+ "@owlmeans/flow": "^0.1.18-rc.46",
69
+ "@owlmeans/i18n": "^0.1.18-rc.40",
70
+ "@owlmeans/log": "^0.1.18-rc.4",
71
+ "@owlmeans/resource": "^0.1.18-rc.41",
72
+ "@owlmeans/socket": "^0.1.18-rc.46",
73
+ "@owlmeans/web-flow": "^0.1.18-rc.60",
74
74
  "@scure/base": "^2.4.0"
75
75
  },
76
76
  "peerDependencies": {
@@ -79,7 +79,7 @@
79
79
  },
80
80
  "devDependencies": {
81
81
  "@owlmeans/dep-config": "workspace:*",
82
- "@owlmeans/test-auth": "^0.1.18-rc.50",
82
+ "@owlmeans/test-auth": "^0.1.18-rc.52",
83
83
  "@types/bun": "^1.4.2",
84
84
  "@types/react": "^19.3.0",
85
85
  "nodemon": "^3.1.14",
@@ -37,7 +37,7 @@ Comprehensive error handling for authentication scenarios:
37
37
  This manager is part of the `@owlmeans/client-auth` package:
38
38
 
39
39
  ```bash
40
- npm install @owlmeans/client-auth@^0.1.18-rc.64
40
+ npm install @owlmeans/client-auth@^0.1.18-rc.66
41
41
  ```
42
42
 
43
43
  ## API Reference