@owlmeans/server-auth 0.1.18-rc.8 → 0.1.18

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.
Files changed (218) hide show
  1. package/README.md +216 -38
  2. package/agent-meta/manifest.json +10 -3
  3. package/agent-meta/skills/server-auth/SKILL.md +161 -22
  4. package/agent-meta/skills/supervisor-auth/SKILL.md +128 -0
  5. package/build/actions/service.d.ts +6 -2
  6. package/build/actions/service.d.ts.map +1 -1
  7. package/build/actions/service.js +5 -4
  8. package/build/actions/service.js.map +1 -1
  9. package/build/actions/types.local.d.ts +6 -0
  10. package/build/actions/types.local.d.ts.map +1 -0
  11. package/build/actions/types.local.js +2 -0
  12. package/build/actions/types.local.js.map +1 -0
  13. package/build/entrypoints.d.ts +5 -0
  14. package/build/entrypoints.d.ts.map +1 -0
  15. package/build/entrypoints.js +9 -0
  16. package/build/entrypoints.js.map +1 -0
  17. package/build/index.d.ts +2 -1
  18. package/build/index.d.ts.map +1 -1
  19. package/build/index.js +2 -1
  20. package/build/index.js.map +1 -1
  21. package/build/manager/actions/authenticate.d.ts +8 -0
  22. package/build/manager/actions/authenticate.d.ts.map +1 -0
  23. package/build/manager/actions/authenticate.js +5 -0
  24. package/build/manager/actions/authenticate.js.map +1 -0
  25. package/build/manager/actions/index.d.ts +3 -1
  26. package/build/manager/actions/index.d.ts.map +1 -1
  27. package/build/manager/actions/index.js +3 -1
  28. package/build/manager/actions/index.js.map +1 -1
  29. package/build/manager/actions/init.d.ts +8 -0
  30. package/build/manager/actions/init.d.ts.map +1 -0
  31. package/build/manager/actions/init.js +5 -0
  32. package/build/manager/actions/init.js.map +1 -0
  33. package/build/manager/actions/rely.d.ts +8 -0
  34. package/build/manager/actions/rely.d.ts.map +1 -0
  35. package/build/manager/actions/rely.js +7 -0
  36. package/build/manager/actions/rely.js.map +1 -0
  37. package/build/manager/consts.local.d.ts +2 -0
  38. package/build/manager/consts.local.d.ts.map +1 -0
  39. package/build/manager/consts.local.js +2 -0
  40. package/build/manager/consts.local.js.map +1 -0
  41. package/build/manager/context.d.ts.map +1 -1
  42. package/build/manager/context.js +0 -1
  43. package/build/manager/context.js.map +1 -1
  44. package/build/manager/entrypoints.d.ts +9 -0
  45. package/build/manager/entrypoints.d.ts.map +1 -0
  46. package/build/manager/entrypoints.js +16 -0
  47. package/build/manager/entrypoints.js.map +1 -0
  48. package/build/manager/exports.d.ts +1 -2
  49. package/build/manager/exports.d.ts.map +1 -1
  50. package/build/manager/exports.js +1 -2
  51. package/build/manager/exports.js.map +1 -1
  52. package/build/manager/index.d.ts +1 -1
  53. package/build/manager/index.d.ts.map +1 -1
  54. package/build/manager/index.js +1 -1
  55. package/build/manager/index.js.map +1 -1
  56. package/build/manager/main.d.ts.map +1 -1
  57. package/build/manager/main.js +2 -2
  58. package/build/manager/main.js.map +1 -1
  59. package/build/manager/model.d.ts.map +1 -1
  60. package/build/manager/model.js +71 -32
  61. package/build/manager/model.js.map +1 -1
  62. package/build/manager/plugins/basic-ed25519.d.ts +1 -1
  63. package/build/manager/plugins/basic-ed25519.d.ts.map +1 -1
  64. package/build/manager/plugins/basic-ed25519.js +6 -6
  65. package/build/manager/plugins/basic-ed25519.js.map +1 -1
  66. package/build/manager/plugins/basic-rely.d.ts +1 -1
  67. package/build/manager/plugins/basic-rely.d.ts.map +1 -1
  68. package/build/manager/plugins/basic-rely.js +11 -8
  69. package/build/manager/plugins/basic-rely.js.map +1 -1
  70. package/build/manager/plugins/consts.d.ts +8 -0
  71. package/build/manager/plugins/consts.d.ts.map +1 -0
  72. package/build/manager/plugins/consts.js +9 -0
  73. package/build/manager/plugins/consts.js.map +1 -0
  74. package/build/manager/plugins/export.d.ts +5 -0
  75. package/build/manager/plugins/export.d.ts.map +1 -1
  76. package/build/manager/plugins/export.js +4 -0
  77. package/build/manager/plugins/export.js.map +1 -1
  78. package/build/manager/plugins/index.d.ts +3 -4
  79. package/build/manager/plugins/index.d.ts.map +1 -1
  80. package/build/manager/plugins/index.js +6 -6
  81. package/build/manager/plugins/index.js.map +1 -1
  82. package/build/manager/plugins/re-captcha/consts.d.ts +7 -0
  83. package/build/manager/plugins/re-captcha/consts.d.ts.map +1 -0
  84. package/build/manager/plugins/re-captcha/consts.js +7 -0
  85. package/build/manager/plugins/re-captcha/consts.js.map +1 -0
  86. package/build/manager/plugins/re-captcha/consts.local.d.ts +7 -0
  87. package/build/manager/plugins/re-captcha/consts.local.d.ts.map +1 -0
  88. package/build/manager/plugins/re-captcha/consts.local.js +9 -0
  89. package/build/manager/plugins/re-captcha/consts.local.js.map +1 -0
  90. package/build/manager/plugins/re-captcha/policy.d.ts +3 -0
  91. package/build/manager/plugins/re-captcha/policy.d.ts.map +1 -0
  92. package/build/manager/plugins/re-captcha/policy.js +44 -0
  93. package/build/manager/plugins/re-captcha/policy.js.map +1 -0
  94. package/build/manager/plugins/re-captcha/types.d.ts +79 -0
  95. package/build/manager/plugins/re-captcha/types.d.ts.map +1 -0
  96. package/build/manager/plugins/re-captcha/types.js +2 -0
  97. package/build/manager/plugins/re-captcha/types.js.map +1 -0
  98. package/build/manager/plugins/re-captcha/verifier.d.ts +12 -0
  99. package/build/manager/plugins/re-captcha/verifier.d.ts.map +1 -0
  100. package/build/manager/plugins/re-captcha/verifier.js +62 -0
  101. package/build/manager/plugins/re-captcha/verifier.js.map +1 -0
  102. package/build/manager/plugins/re-captcha.d.ts +10 -1
  103. package/build/manager/plugins/re-captcha.d.ts.map +1 -1
  104. package/build/manager/plugins/re-captcha.js +50 -37
  105. package/build/manager/plugins/re-captcha.js.map +1 -1
  106. package/build/manager/plugins/supervisor.d.ts +1 -2
  107. package/build/manager/plugins/supervisor.d.ts.map +1 -1
  108. package/build/manager/plugins/supervisor.js +6 -6
  109. package/build/manager/plugins/supervisor.js.map +1 -1
  110. package/build/manager/plugins/types.d.ts +22 -14
  111. package/build/manager/plugins/types.d.ts.map +1 -1
  112. package/build/manager/plugins/utils.d.ts +5 -4
  113. package/build/manager/plugins/utils.d.ts.map +1 -1
  114. package/build/manager/plugins/utils.js +20 -15
  115. package/build/manager/plugins/utils.js.map +1 -1
  116. package/build/manager/rely/flow.d.ts.map +1 -1
  117. package/build/manager/rely/flow.js +13 -11
  118. package/build/manager/rely/flow.js.map +1 -1
  119. package/build/manager/rely.d.ts.map +1 -1
  120. package/build/manager/rely.js.map +1 -1
  121. package/build/manager/supervisor.d.ts +4 -45
  122. package/build/manager/supervisor.d.ts.map +1 -1
  123. package/build/manager/supervisor.js +5 -5
  124. package/build/manager/supervisor.js.map +1 -1
  125. package/build/manager/types.d.ts +41 -1
  126. package/build/manager/types.d.ts.map +1 -1
  127. package/build/manager/types.local.d.ts +4 -0
  128. package/build/manager/types.local.d.ts.map +1 -0
  129. package/build/manager/types.local.js +2 -0
  130. package/build/manager/types.local.js.map +1 -0
  131. package/build/manager/utils/trusted.d.ts.map +1 -1
  132. package/build/manager/utils/trusted.js.map +1 -1
  133. package/build/model/rely/consumer.d.ts +3 -1
  134. package/build/model/rely/consumer.d.ts.map +1 -1
  135. package/build/model/rely/consumer.js.map +1 -1
  136. package/build/model/rely/peer.d.ts.map +1 -1
  137. package/build/model/rely/peer.js +7 -7
  138. package/build/model/rely/peer.js.map +1 -1
  139. package/build/model/rely/provider.d.ts +3 -1
  140. package/build/model/rely/provider.d.ts.map +1 -1
  141. package/build/model/rely/provider.js.map +1 -1
  142. package/build/re-captcha/guard.d.ts +12 -0
  143. package/build/re-captcha/guard.d.ts.map +1 -0
  144. package/build/re-captcha/guard.js +43 -0
  145. package/build/re-captcha/guard.js.map +1 -0
  146. package/build/re-captcha/index.d.ts +4 -0
  147. package/build/re-captcha/index.d.ts.map +1 -0
  148. package/build/re-captcha/index.js +3 -0
  149. package/build/re-captcha/index.js.map +1 -0
  150. package/build/re-captcha/token.d.ts +6 -0
  151. package/build/re-captcha/token.d.ts.map +1 -0
  152. package/build/re-captcha/token.js +74 -0
  153. package/build/re-captcha/token.js.map +1 -0
  154. package/build/re-captcha/types.d.ts +44 -0
  155. package/build/re-captcha/types.d.ts.map +1 -0
  156. package/build/re-captcha/types.js +2 -0
  157. package/build/re-captcha/types.js.map +1 -0
  158. package/build/service.d.ts +2 -3
  159. package/build/service.d.ts.map +1 -1
  160. package/build/service.js +136 -13
  161. package/build/service.js.map +1 -1
  162. package/build/types.local.d.ts +4 -0
  163. package/build/types.local.d.ts.map +1 -0
  164. package/build/types.local.js +2 -0
  165. package/build/types.local.js.map +1 -0
  166. package/package.json +33 -30
  167. package/src/actions/service.ts +10 -12
  168. package/src/actions/types.local.ts +6 -0
  169. package/src/entrypoints.ts +12 -0
  170. package/src/index.ts +2 -2
  171. package/src/manager/README.md +14 -18
  172. package/src/manager/actions/authenticate.ts +12 -0
  173. package/src/manager/actions/index.ts +3 -1
  174. package/src/manager/actions/init.ts +12 -0
  175. package/src/manager/actions/rely.ts +12 -0
  176. package/src/manager/consts.local.ts +1 -0
  177. package/src/manager/context.ts +0 -2
  178. package/src/manager/entrypoints.ts +17 -0
  179. package/src/manager/exports.ts +1 -2
  180. package/src/manager/index.ts +1 -1
  181. package/src/manager/main.ts +2 -2
  182. package/src/manager/model.ts +82 -41
  183. package/src/manager/plugins/basic-ed25519.ts +8 -8
  184. package/src/manager/plugins/basic-rely.ts +14 -9
  185. package/src/manager/plugins/consts.ts +7 -0
  186. package/src/manager/plugins/export.ts +5 -0
  187. package/src/manager/plugins/index.ts +10 -12
  188. package/src/manager/plugins/re-captcha/consts.local.ts +8 -0
  189. package/src/manager/plugins/re-captcha/consts.ts +8 -0
  190. package/src/manager/plugins/re-captcha/policy.ts +56 -0
  191. package/src/manager/plugins/re-captcha/types.ts +85 -0
  192. package/src/manager/plugins/re-captcha/verifier.ts +74 -0
  193. package/src/manager/plugins/re-captcha.ts +58 -43
  194. package/src/manager/plugins/supervisor.ts +9 -11
  195. package/src/manager/plugins/types.ts +23 -14
  196. package/src/manager/plugins/utils.ts +24 -14
  197. package/src/manager/rely/flow.ts +14 -11
  198. package/src/manager/rely.ts +2 -5
  199. package/src/manager/supervisor.ts +8 -54
  200. package/src/manager/types.local.ts +5 -0
  201. package/src/manager/types.ts +46 -1
  202. package/src/model/rely/consumer.ts +3 -1
  203. package/src/model/rely/peer.ts +8 -8
  204. package/src/model/rely/provider.ts +3 -1
  205. package/src/re-captcha/guard.ts +52 -0
  206. package/src/re-captcha/index.ts +3 -0
  207. package/src/re-captcha/token.ts +89 -0
  208. package/src/re-captcha/types.ts +45 -0
  209. package/src/service.ts +133 -19
  210. package/src/types.local.ts +5 -0
  211. package/tests/context.ts +3 -2
  212. package/tests/re-captcha.spec.ts +298 -0
  213. package/tests/replay-policy.spec.ts +36 -0
  214. package/tests/supervisor.spec.ts +6 -4
  215. package/build/.gitkeep +0 -0
  216. package/src/manager/actions/manager.ts +0 -23
  217. package/src/manager/modules.ts +0 -29
  218. package/src/modules.ts +0 -17
package/README.md CHANGED
@@ -1,72 +1,250 @@
1
1
  # @owlmeans/server-auth
2
2
 
3
- Server-side Ed25519 authentication service for OwlMeans backends.
4
-
5
- ## Overview
6
-
7
- - Implements the `GuardService` interface for Ed25519-signed token verification
8
- - `appendAuthService()` registers the auth guard into a server context
9
- - `DEFAULT_ALIAS` (`'auth'`) is the service alias and re-exported as `DAUTH_GUARD` via `@owlmeans/server-app`
10
- - Handles token caching via a static resource identified by `AUTH_CACHE`
3
+ The server side of OwlMeans authentication, in two halves. The root export is what every protected
4
+ API service needs: the guard that verifies an Ed25519-signed bearer token and resolves
5
+ `request.auth`, and the dispatcher bindings that exchange a credential issued by the auth manager
6
+ for a bearer of this service. The `./manager` subpath is the auth manager application itself — the
7
+ challenge endpoints, the authentication plugin registry, the signed credential envelope and the rely
8
+ handshake. An ordinary service imports the root (usually implicitly, through
9
+ `@owlmeans/server-app`'s `makeContext`); only the auth manager imports `./manager`. OIDC tokens are
10
+ `@owlmeans/server-oidc-rp`, long-lived API keys `@owlmeans/server-auth-token`, local
11
+ account/profile records `@owlmeans/server-auth-identity`, and the browser side `@owlmeans/client-auth`.
11
12
 
12
13
  ## Installation
13
14
 
14
15
  ```bash
15
- bun add @owlmeans/server-auth
16
+ bun add @owlmeans/server-auth@^0.1.18
16
17
  ```
17
18
 
19
+ ## Concepts
20
+
21
+ - **Guard** — the `AuthService` registered as `auth` (the value of `DEFAULT_GUARD`). `match` hits a
22
+ request carrying an `ed25519-basic-token`; `handle` verifies it against this service's own trusted
23
+ key (`cfg.alias ?? cfg.service`) and resolves the `Auth`. It authenticates only — authorization is
24
+ gates and handlers.
25
+ - **Token exchange** — `authenticate(token)` verifies a credential envelope against the
26
+ `auth-service` trusted record (`AUTH_SRV_KEY`), burns its challenge into `AUTH_CACHE`, and returns
27
+ a bearer signed by this service.
28
+ - **`AUTH_CACHE`** — the anti-replay store: each challenge is created once with an
29
+ `AUTHEN_TIMEFRAME` TTL. A static in-process resource by default.
30
+ - **Auth manager** — the `./manager` application: `init(request)` returns a challenge,
31
+ `authenticate(credential)` returns a signed credential envelope, and the slug on the credential is
32
+ canonicalized through the entity resolver before signing.
33
+ - **Authentication plugin** — `{ type, init, authenticate }` registered under an
34
+ `AuthenticationType`; the manager dispatches by the request's `type`.
35
+ - **Rely** — the wallet handshake that lets one authenticated party vouch for another over a socket
36
+ (`DEFAULT_RELY` guard, `RELY_TUNNEL`).
37
+
18
38
  ## Usage
19
39
 
20
- Registered automatically by `makeContext()` from `@owlmeans/server-app`. To customize, pass `customize: true` and append manually:
40
+ ### Protect routes on an ordinary service
21
41
 
22
- ```typescript
23
- import { makeContext } from '@owlmeans/server-app'
24
- import { appendAuthService, AUTH_CACHE } from '@owlmeans/server-auth'
42
+ `@owlmeans/server-app`'s `makeContext(cfg)` registers the guard. A protocol opts in with `guards`,
43
+ and everything declared under it inherits them.
25
44
 
26
- const context = makeContext(appConfig, true) // skip default auth
45
+ ```ts
46
+ import { contract, openProtocol, protocol, typed } from '@owlmeans/entrypoint'
47
+ import { route, RouteMethod } from '@owlmeans/route'
48
+ import { DEFAULT_GUARD } from '@owlmeans/auth-common'
27
49
 
28
- // Append auth with custom config
29
- appendAuthService(context)
50
+ const invoiceBase = openProtocol(route('my-app:api:invoice', '/invoice'), { guards: DEFAULT_GUARD })
51
+
52
+ export const invoiceProtocols = {
53
+ base: invoiceBase,
54
+ list: protocol(
55
+ route('my-app:api:invoice:list', '/', { parent: invoiceBase, method: RouteMethod.GET }),
56
+ contract(typed<Invoice[]>()),
57
+ ),
58
+ }
30
59
  ```
31
60
 
32
- Reference the guard by alias when protecting routes:
61
+ ```ts
62
+ import { handlers } from '@owlmeans/server-app'
63
+ import { makeEntityScope } from '@owlmeans/auth-common'
33
64
 
34
- ```typescript
35
- import { DAUTH_GUARD } from '@owlmeans/server-app'
36
- // same as DEFAULT_ALIAS from @owlmeans/server-auth
65
+ const api = handlers<Context>()
37
66
 
38
- const adminModule = module(route('admin', '/admin'), guard(DAUTH_GUARD))
67
+ export const list = api.request(invoiceProtocols.list, async (request, context) => {
68
+ // request.auth is the verified Auth: userId, profileId, role, scopes, entitySlug
69
+ const { items } = await context.invoice().list({ entityId: makeEntityScope(request).requireEntityKey() })
70
+ return items
71
+ })
39
72
  ```
40
73
 
41
- ## API
74
+ ### Scaled deployment
75
+
76
+ Replace the in-process cache with a shared one before registering the guard, and declare the trusted
77
+ keys the guard verifies against.
78
+
79
+ ```ts
80
+ import { makeContext as makeAppContext } from '@owlmeans/server-app'
81
+ import { appendRedis } from '@owlmeans/redis'
82
+ import { makeRedisResource } from '@owlmeans/redis-resource'
83
+ import { appendAuthService, AUTH_CACHE, AUTH_SRV_KEY } from '@owlmeans/server-auth'
84
+ import { appendAuthIdentityResources } from '@owlmeans/server-auth-identity'
85
+
86
+ // config.ts — keys are loaded from the environment, never committed
87
+ cfg.trusted.push({
88
+ id: process.env.AUTH_SERVICE_DID!, name: AUTH_SRV_KEY,
89
+ credential: process.env.AUTH_SERVICE_PUB!, scopes: ['*'],
90
+ })
91
+ cfg.trusted.push({
92
+ id: process.env.MY_APP_API_DID!, name: MY_APP_API,
93
+ credential: process.env.MY_APP_API_PUB!, secret: process.env.MY_APP_API_PK!, scopes: ['*'],
94
+ })
95
+
96
+ // context.ts
97
+ export const makeContext = <C extends Config, T extends Context<C>>(cfg: C): T => {
98
+ const context = makeAppContext<C, T>(cfg, true)
99
+ appendRedis<C, T>(context)
100
+
101
+ context.registerResource(makeRedisResource(AUTH_CACHE))
102
+ appendAuthService<C, T>(context)
103
+ appendAuthIdentityResources(context)
104
+
105
+ return context
106
+ }
107
+ ```
108
+
109
+ ### Verify a token outside the HTTP pipeline
110
+
111
+ ```ts
112
+ import type { AuthServiceAppend } from '@owlmeans/server-auth'
113
+
114
+ const readAuth = async (context: Context & AuthServiceAppend, authorization: string) =>
115
+ context.auth().unpack(authorization) // 'ED25519-BASIC-TOKEN <envelope>' -> Auth, or throws
116
+ ```
117
+
118
+ ### Run the auth manager
119
+
120
+ ```ts
121
+ import { config, makeContext, main } from '@owlmeans/server-auth/manager'
122
+ import type { AppConfig } from '@owlmeans/server-auth/manager'
123
+ import '@owlmeans/server-oidc-rp/auth/plugins' // optional: OIDC and Google login plugins
124
+
125
+ const cfg = config<AppConfig>(MY_APP_AUTH, commonConfig as AppConfig)
126
+ const context = makeContext(cfg)
127
+
128
+ await main(context)
129
+ ```
130
+
131
+ ### Add an authentication method
132
+
133
+ ```ts
134
+ import { registerPlugin } from '@owlmeans/server-auth/manager/plugins'
135
+ import type { AuthPlugin } from '@owlmeans/server-auth/manager/plugins'
42
136
 
43
- ### `appendAuthService<C, T>(context): void`
137
+ registerPlugin('my-method', context => ({
138
+ type: 'my-method',
139
+ init: async request => ({ challenge: /* unique per request */ '' }),
140
+ authenticate: async credential => {
141
+ // verify credential.credential, then set userId / profileId / entitySlug / role / scopes
142
+ return { token: '' } // '' keeps the manager's own challenge as the credential token
143
+ },
144
+ }) as AuthPlugin)
145
+ ```
146
+
147
+ ### Accept a reCAPTCHA-proven guest on one route
148
+
149
+ The manager's reCAPTCHA plugin signs a GUEST token (`GUEST_ID`, role Guest, `[AUTH_SCOPE]`) whatever
150
+ identity the caller posts. A route takes it through the reCAPTCHA guard, which spends it once:
151
+
152
+ ```ts
153
+ import { CMOD_RECAPTCHA, MOD_RECAPTCHA, RECAPTCHA_GUARD } from '@owlmeans/auth'
154
+ import { clientPlugin, plugin } from '@owlmeans/config'
155
+ import { makeReCaptchaGuard, reCaptchaTokenOf } from '@owlmeans/server-auth'
44
156
 
45
- Registers the Ed25519 auth service and its nonce cache resource into the context.
157
+ // config: the secret plus the policy (strings, '' = no check), and the browser's site key
158
+ plugin(cfg, {
159
+ value: '/etc/master-secret/recaptcha-secret',
160
+ hostnames: 'example.org, example.com', minScore: '0.5', actions: 'inquiry',
161
+ }, MOD_RECAPTCHA)
162
+ clientPlugin(cfg, '/etc/app-config/recaptcha-site-key', CMOD_RECAPTCHA)
163
+
164
+ // context: the guard of the route's `guards: [RECAPTCHA_GUARD]` (`Authorization: RE-CAPTCHA <token>`)
165
+ context.registerService(makeReCaptchaGuard())
166
+ // a pre-parse check that does not spend:
167
+ const guest = await reCaptchaTokenOf(context).inspect(request) // null = 401
168
+ ```
169
+
170
+ ## API
46
171
 
47
- ### `makeAuthService(alias?): AuthService`
172
+ ### Root export
48
173
 
49
- Creates the auth service directly (used internally by `appendAuthService`).
174
+ | Symbol | Kind | Purpose |
175
+ |---|---|---|
176
+ | `appendAuthService(ctx, alias = DEFAULT_ALIAS)` | function | Register the guard as `context.auth()`; registers a static `AUTH_CACHE` when the context has none |
177
+ | `makeAuthService(alias?)` | function | The guard: `match`, `handle`, `unpack(token)`, `authenticate(token)` |
178
+ | `entrypoints` | const | Server bindings of `authProtocols.dispatcher` and `authProtocols.dispatcherAuthenticate` |
179
+ | `DEFAULT_ALIAS` | const | `'auth'` — equals `DEFAULT_GUARD`; re-exported as `DAUTH_GUARD` by `@owlmeans/server-app` |
180
+ | `AUTH_CACHE` | const | `'auth-cache'` — the single-use challenge store |
181
+ | `AUTH_SRV_KEY` | const | `'auth-service'` — the trusted record whose key signs credential envelopes |
182
+ | `AUTHEN_TIMEFRAME` | const | `15 * 60 * 1000` ms — challenge lifetime and anti-replay window |
183
+ | `makeRelyModel`, `makeProviderRely`, `makeConsumerRely` | function | Rely envelope models |
184
+ | `AuthService`, `AuthServiceAppend`, `AuthSpent`, `RelyOptions` | type | Guard service, context mixin, cache record, rely options |
185
+ | `makeReCaptchaGuard(alias = RECAPTCHA_GUARD)` | function | Guard of a route a reCAPTCHA guest calls once: verifies and spends `RE-CAPTCHA <token>` |
186
+ | `makeReCaptchaTokenHelper(ctx)`, `reCaptchaTokenOf(ctx)` | function | `inspect(req)` / `verify(token)` (no spend) and `spend(guest)` |
187
+ | `ReCaptchaGuest`, `ReCaptchaCarrier`, `ReCaptchaTokenHelper` | type | Inspection result, header carrier, token checks |
50
188
 
51
- ### `DEFAULT_ALIAS`
189
+ ### `./manager`
52
190
 
53
- The auth service alias: `'auth'`. Re-exported as `DAUTH_GUARD` from `@owlmeans/server-app`.
191
+ | Symbol | Kind | Purpose |
192
+ |---|---|---|
193
+ | `makeContext(cfg, customize?)` | function | Server context with API server, API client, socket service, rely guard and static `AUTH_CACHE` |
194
+ | `main(ctx)` | function | Register the manager entrypoints, init and listen |
195
+ | `entrypoints` | const | Bindings for authen, init, authenticate, rely and api-config |
196
+ | `authenticationInit`, `authenticate`, `rely` | function | Implementations bound to the auth protocols |
197
+ | `plugins`, `registerPlugin(type, factory)` | const / function | The plugin registry |
198
+ | `appendSupervisorAuth(ctx, opts?)`, `setupInternalTokenCoguard(entrypoints, guard?)` | function | PK supervisor login (development only by default) |
199
+ | `createRelyService(alias?)`, `createRelyFlow(context, conn, auth?)` | function | Rely guard service and socket authentication flow |
200
+ | `DEFAULT_RELY`, `RELY_TUNNEL` | const | `'auth-rely'`, `'rely-tunnel'` |
201
+ | `config`, `service`, `TRUSTED`, `addWebService`, `AppType`, `assertContext`, `klusterize`, `stab`, `backend`, `filterObject` | re-export | Config and context helpers for a manager app |
202
+ | `handleIntermediate`, `handleBody`, `handleRequest`, `handleParams` | re-export | `@owlmeans/server-api` wrappers |
203
+ | `AUTHEN`, `AUTHEN_AUTHEN`, `AUTHEN_INIT`, `GUARD_ED25519`, `BED255_CASHE_RESOURCE` | re-export | Auth aliases |
204
+ | `AppConfig`, `AppContext`, `AuthModel`, `RelyService`, `RelyAllowanceRequest`, `RelyLinker`, `RelyCarrier` | type | Manager shapes |
205
+ | `SupervisorAuthOptions`, `SupervisorUserResolver`, `SupervisorUserResolution`, `SupervisorPluginOptions` | type | Supervisor options |
206
+ | `TrustedRecord`, `RefedEntrypointHandler`, `AbstractRequest`, `AbstractResponse` | type | Re-exported types |
54
207
 
55
- ### `AUTH_CACHE`
208
+ ### `./manager/plugins`
56
209
 
57
- Resource alias for the nonce replay-prevention cache.
210
+ | Symbol | Kind | Purpose |
211
+ |---|---|---|
212
+ | `registerPlugin(type, factory)`, `plugins` | function / const | The module-level registry |
213
+ | `authPluginHelper.getPlugin(type, context)`, `authPluginHelper.assertType(type, plugin)` | method | Resolution; `getPlugin` throws `AuthUnknown(type)` for an unregistered type |
214
+ | `makeBasicEd25519Plugin`, `makeReCaptchaPlugin`, `makeBasicRelyPlugin` | function | Built-in plugin factories |
215
+ | `makeSupervisorPlugin(context, opts)` | function | PK supervisor plugin factory |
216
+ | `createReCaptchaVerifierService(alias?, opts?)`, `appendReCaptchaVerifierService(ctx, alias?, opts?)` | function | Google siteverify over `fetch` (https only); the plugin's seam |
217
+ | `makeReCaptchaPolicyModel(record)` | function | The `MOD_RECAPTCHA` record's policy: `hostnames()`, `minScore()`, `actions()`, `assert(answer)` |
218
+ | `RECAPTCHA_VERIFIER`, `RECAPTCHA_SITEVERIFY_URL`, `RECAPTCHA_VERIFY_TIMEOUT` | const | `'re-captcha-verifier'`, Google's endpoint, 10 s |
219
+ | `AuthPlugin`, `AuthPluginFactory`, `AuthPluginHelper`, `RelyRecord`, `AuthRedisResource` | type | Plugin shapes |
220
+ | `ReCaptchaResponse`, `ReCaptchaRequest`, `ReCaptchaVerifierService`, `ReCaptchaVerifierOptions`, `ReCaptchaFetch`, `ReCaptchaPluginConfig`, `ReCaptchaPolicyModel` | type | reCAPTCHA shapes |
58
221
 
59
- ## Product-Viable Integration Notes
222
+ ## Common pitfalls
60
223
 
61
- - Register `appendAuthService(context)` before `appendAuthIdentityResources(context)` and product-specific gate services.
62
- - Register `AUTH_CACHE` explicitly as a Redis resource when customizing the backend context.
63
- - This package verifies bearer tokens and populates `request.auth`; authorization remains the job of module gates and handler-level entity checks.
64
- - Pair it with `@owlmeans/server-auth-identity` when external provider login should produce durable local account/profile/credentials records.
224
+ - The guard verifies a bearer and sets `request.auth`; it decides nothing about ownership. Pair it
225
+ with gates and keep a handler-level organization check.
226
+ - The default static `AUTH_CACHE` is correct for one replica only. Register a Redis resource under
227
+ the same alias before `appendAuthService` in any scaled deployment.
228
+ - A plugin's `init` must return a challenge unique per request; a repeated challenge collides in
229
+ `AUTH_CACHE` and fails as `AuthenFailed('challenge')`.
230
+ - The manager replaces whatever slug a plugin sets on `credential.entitySlug` with the current slug;
231
+ an unresolvable value fails as `AuthenFailed('entity')`. A token carries `entitySlug`, never an
232
+ entity id.
233
+ - Register `appendAuthService` before `appendAuthIdentityResources` and product gate services.
234
+ - Import `./manager` only in the auth manager process.
235
+ - A reCAPTCHA token is a guest token: the bearer exchange (`authenticate`) refuses it, and only
236
+ `makeReCaptchaGuard` accepts it — once.
65
237
 
66
- ## Related Packages
238
+ ## Related packages
67
239
 
68
- - [`@owlmeans/auth-common`](../auth-common) — `GUARD_ED25519` constant and auth modules
240
+ - [`@owlmeans/auth`](../auth) — `Auth`, `AuthCredentials`, error classes
241
+ - [`@owlmeans/auth-common`](../auth-common) — `DEFAULT_GUARD`, `authProtocols`, `trust()`, entity helpers
242
+ - [`@owlmeans/server-auth-identity`](../server-auth-identity) — local identity records and the entity resolver
243
+ - [`@owlmeans/server-oidc-rp`](../server-oidc-rp) — OIDC login plugins and guard
244
+ - [`@owlmeans/server-auth-otp`](../server-auth-otp) — email OTP plugin
245
+ - [`@owlmeans/server-auth-token`](../server-auth-token) — long-lived access tokens
69
246
  - [`@owlmeans/server-app`](../server-app) — `makeContext` calls `appendAuthService` by default
247
+ - [`@owlmeans/client-auth`](../client-auth) — the browser side
70
248
 
71
249
  <!-- owlmeans:agent-guidance:start -->
72
250
  ## Agent guidance
@@ -76,7 +254,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
76
254
  your project's skill store (`.agents/skills/`):
77
255
 
78
256
  ```sh
79
- npx @owlmeans/agent-skills
257
+ npx @owlmeans/agent-skills@^0.1.18
80
258
  ```
81
259
 
82
260
  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/server-auth",
4
- "version": "0.1.18-rc.7",
5
- "generatedAt": "2026-08-21T09:53:56.640Z",
4
+ "version": "0.1.18",
5
+ "generatedAt": "2026-10-28T00:31:34.722Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -11,6 +11,13 @@
11
11
  "category": "package-specific",
12
12
  "file": "skills/server-auth/SKILL.md",
13
13
  "canonicalPath": ".agents/skills/server-auth/SKILL.md"
14
+ },
15
+ {
16
+ "kind": "skill",
17
+ "name": "supervisor-auth",
18
+ "category": "multi-package",
19
+ "file": "skills/supervisor-auth/SKILL.md",
20
+ "canonicalPath": ".agents/skills/supervisor-auth/SKILL.md"
14
21
  }
15
22
  ]
16
23
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: server-auth
3
- description: How to use @owlmeans/server-auth — server-side authentication manager, AUTH_API alias, setupAuthServiceModules() to wire auth modules into your app. Auto-invoked when importing auth manager primitives.
3
+ description: How to use @owlmeans/server-auth — the server side of OwlMeans authentication. Two halves in one package - appendAuthService/makeAuthService, which verify Ed25519 bearer tokens on an ordinary API server, and the ./manager subpath, which IS the auth manager service (challenge, plugin registry, credential envelope, rely). Also the reCAPTCHA guest path - the plugin's verifier and policy record, and makeReCaptchaGuard, which spends a guest token once. Auto-invoked when importing the server auth guard or the reCAPTCHA guard, registering an auth plugin, or building the auth manager.
4
4
  user-invocable: false
5
5
  ---
6
6
  <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
@@ -8,41 +8,180 @@ user-invocable: false
8
8
  # @owlmeans/server-auth
9
9
 
10
10
  **Layer:** Server
11
- **Install:** `"@owlmeans/server-auth": "^0.1.18-rc.7"` in `dependencies`
11
+ **Install:** `"@owlmeans/server-auth": "^0.1.18"` in `dependencies`
12
12
 
13
- ## Key Exports
13
+ Two halves, deliberately split by subpath:
14
+
15
+ - the **root** export is what every protected API server needs — the guard that verifies an
16
+ `Ed25519BasicToken` bearer and resolves an `Auth`;
17
+ - **`./manager`** is the auth manager application itself — it serves `/authentication/init` and
18
+ `/authentication/authenticate`, owns the plugin registry, and signs the credential envelope.
19
+
20
+ An ordinary service imports the root. Only the auth manager imports `./manager`.
21
+
22
+ ## Key Exports — root
23
+
24
+ | Export | Description |
25
+ |--------|-------------|
26
+ | `appendAuthService(ctx, alias?)` | Register the guard on a server context and expose it as `context.auth()`. Registers a static `AUTH_CACHE` resource when the context has none |
27
+ | `makeAuthService(alias?)` | The guard service itself: `match`, `handle`, `unpack(token)`, `authenticate(token)` |
28
+ | `entrypoints` | `DISPATCHER` and `DISPATCHER_AUTHEN`, server-bound — spread these into a service that accepts a manager-issued credential and exchanges it for a bearer |
29
+ | `DEFAULT_ALIAS` | `'auth'` — the guard's service alias, matching `DEFAULT_GUARD` |
30
+ | `AUTH_CACHE` | `'auth-cache'` — the single-use challenge store |
31
+ | `AUTH_SRV_KEY` | `'auth-service'` — the TRUSTED record whose key signs credential envelopes |
32
+ | `AUTHEN_TIMEFRAME` | `15 * 60 * 1000` — challenge lifetime and anti-replay window, in ms |
33
+ | `AuthService`, `AuthServiceAppend`, `AuthSpent` | Types |
34
+ | `makeRelyModel`, `makeProviderRely`, `makeConsumerRely`, `RelyOptions` | The rely (wallet handshake) models |
35
+ | `makeReCaptchaGuard(alias = RECAPTCHA_GUARD)` | The guard of a route a reCAPTCHA guest calls once — see "reCAPTCHA guests" |
36
+ | `makeReCaptchaTokenHelper(ctx)`, `reCaptchaTokenOf(ctx)` | `inspect(req)` / `verify(token)` → `ReCaptchaGuest \| null` without spending; `spend(guest)` → `false` when spent before |
37
+ | `ReCaptchaGuest`, `ReCaptchaCarrier`, `ReCaptchaTokenHelper` | Types: `{ credential, challenge, expiresAt }`, `{ headers? }`, the helper |
38
+
39
+ ## Key Exports — `./manager`
14
40
 
15
41
  | Export | Description |
16
42
  |--------|-------------|
17
- | `setupAuthServiceModules(modules, alias)` | Wire auth modules into your app modules array |
18
- | `AUTH_API` (re-exported) | Auth service alias |
19
- | Auth service factory | Backend auth manager |
20
- | Plugin types | Pluggable auth verifiers |
43
+ | `makeContext(cfg, customize?)` | A server context preconfigured with the API server, API client, socket service and static `AUTH_CACHE` |
44
+ | `main(ctx)` | Register the manager entrypoints, configure, init and listen |
45
+ | `entrypoints` | `AUTHEN`, `AUTHEN_INIT`, `AUTHEN_AUTHEN`, `AUTHEN_RELY` and the api-config entrypoints |
46
+ | `authenticationInit`, `authenticate`, `rely` | Implementations bound to auth protocols: `init(request)` → challenge, `authenticate(credential)` → signed credential envelope, and the rely socket |
47
+ | `plugins`, `registerPlugin(type, factory)` | The plugin registry (also on `./manager/plugins`) |
48
+ | `appendSupervisorAuth(ctx, opts?)`, `setupInternalTokenCoguard(entrypoints, guard?)` | PK supervisor login — see the `supervisor-auth` skill |
49
+ | `createRelyService(alias?)`, `DEFAULT_RELY`, `RELY_TUNNEL` | The rely guard service |
50
+ | `AppConfig`, `AppContext`, `AuthModel`, `RelyService`, `RelyAllowanceRequest`, `RelyLinker`, `RelyCarrier` | Types |
21
51
 
22
- ## Subpath Exports
52
+ `./manager` also re-exports the handful of symbols a manager application needs from elsewhere
53
+ (`config`, `service`, `TRUSTED`, `bind`, `handlers`, `backend`,
54
+ `GUARD_ED25519`, `AUTHEN*` aliases, `TrustedRecord`), so a manager app can be written against this
55
+ one import.
23
56
 
24
- - `./manager` — auth manager service implementation
25
- - `./manager/plugins` — pluggable manager plugins
57
+ ## Key Exports — `./manager/plugins`
58
+
59
+ | Export | Description |
60
+ |--------|-------------|
61
+ | `AuthPlugin` | `{ type, init(request), authenticate(credential) }` — `AuthModel` minus `rely` |
62
+ | `registerPlugin(type, factory)` | Add a plugin under a type string. The registry is a module-level singleton |
63
+ | `plugins` | The registry map |
64
+ | `authPluginHelper.getPlugin(type, context)`, `authPluginHelper.assertType(type, plugin)` | Resolution; `getPlugin` throws `AuthUnknown(type)` for an unregistered type |
65
+ | `makeBasicEd25519Plugin`, `makeReCaptchaPlugin`, `makeBasicRelyPlugin` | The plugin factories registered out of the box, for `AuthenticationType.BasicEd25519`, `ReCaptcha` and `RelyHandshake` |
66
+ | `makeSupervisorPlugin(context, opts)` | The PK supervisor plugin factory |
67
+ | `createReCaptchaVerifierService(alias = RECAPTCHA_VERIFIER, opts?)`, `appendReCaptchaVerifierService(ctx, alias?, opts?)` | Google siteverify: one `fetch` form POST (`opts.url` must be https, `opts.fetch` injectable, `opts.timeout` default 10 s) |
68
+ | `makeReCaptchaPolicyModel(record)` | The `MOD_RECAPTCHA` record's policy: `hostnames()`, `minScore()`, `actions()`, `assert(answer)` |
69
+ | `RECAPTCHA_VERIFIER`, `RECAPTCHA_SITEVERIFY_URL`, `RECAPTCHA_VERIFY_TIMEOUT` | `'re-captcha-verifier'`, `https://www.google.com/recaptcha/api/siteverify`, `10_000` |
70
+ | `ReCaptchaResponse`, `ReCaptchaRequest`, `ReCaptchaVerifierService`, `ReCaptchaVerifierOptions`, `ReCaptchaFetch`, `ReCaptchaPluginConfig`, `ReCaptchaPolicyModel` | reCAPTCHA types |
71
+ | `RelyRecord`, `AuthRedisResource` | Types |
26
72
 
27
73
  ## Usage
28
74
 
75
+ Protect an ordinary API server:
76
+
77
+ ```typescript
78
+ import { appendAuthService } from '@owlmeans/server-auth'
79
+ import { appendAuthIdentityResources } from '@owlmeans/server-auth-identity'
80
+
81
+ // in makeContext, after the db/cache services are appended:
82
+ appendAuthService(context)
83
+ appendAuthIdentityResources(context)
84
+ ```
85
+
86
+ Add an authentication method to the manager:
87
+
29
88
  ```typescript
30
- import { setupAuthServiceModules } from '@owlmeans/server-auth'
31
- import { AUTH_API } from '@owlmeans/auth-common'
89
+ import { registerPlugin } from '@owlmeans/server-auth/manager/plugins'
90
+ import type { AuthPlugin } from '@owlmeans/server-auth/manager/plugins'
32
91
 
33
- setupAuthServiceModules(appModules, AUTH_API)
92
+ registerPlugin('my-method', context => ({
93
+ type: 'my-method',
94
+ init: async request => ({ challenge: /* unique per request */ '' }),
95
+ authenticate: async credential => {
96
+ // verify credential.credential, then set userId / profileId / entitySlug / role / scopes
97
+ return { token: '' } // '' keeps the manager's own challenge as the credential token
98
+ },
99
+ }) as AuthPlugin)
34
100
  ```
35
101
 
36
- ## Product-Viable Usage Notes
102
+ ## reCAPTCHA guests
103
+
104
+ A reCAPTCHA sign-in proves that a person solved a challenge — nothing about who they are.
105
+
106
+ **Config.** One Backend plugin record `MOD_RECAPTCHA` holds the secret in `value` and the policy in
107
+ extra string fields (`''` or absent = no check; each may be a file path the file config reader
108
+ resolves); the browser's site key is a separate Frontend record `CMOD_RECAPTCHA`. Only Frontend
109
+ records are advertised, so the secret and the policy never reach a browser.
110
+
111
+ ```ts
112
+ plugin(cfg, { value: '/etc/master-secret/recaptcha-secret',
113
+ hostnames: 'example.org, example.com', minScore: '0.5', actions: 'inquiry' }, MOD_RECAPTCHA)
114
+ clientPlugin(cfg, '/etc/app-config/recaptcha-site-key', CMOD_RECAPTCHA)
115
+ ```
116
+
117
+ | Field | Check (refusal) |
118
+ |---|---|
119
+ | `value` | the siteverify secret; missing or `''` → `PluginMissconfigured('value')` before Google is asked |
120
+ | — | Google's `success` (`AuthenFailed('recaptcha:<error-codes>')`, `recaptcha:unknown` without codes) |
121
+ | `hostnames` | comma/space list; the answer's `hostname` equals an entry or is its subdomain (`recaptcha:hostname`) |
122
+ | `minScore` | 0…1; a score-based answer with `score < minScore` (`recaptcha:score`); a checkbox answer has no score and passes; a non-number → `PluginMissconfigured('minScore')` |
123
+ | `actions` | comma/space list; the answer's `action` must be one of them — an answer without one fails (`recaptcha:action`) |
124
+
125
+ **Plugin.** `makeReCaptchaPlugin` asks the verifier registered under `RECAPTCHA_VERIFIER` (a test
126
+ or proxy registers its own; without one the default siteverify `fetch` runs — Google is always
127
+ https, `cfg.security.unsecure` does not apply). Google unreachable or answering garbage is
128
+ `AuthUnavailable` (503), never a refusal. After a passing answer the credential keeps ONLY `type`,
129
+ `role`, `userId`, `scopes`, `challenge`, `credential`, set to a guest: `GUEST_ID`, `AuthRole.Guest`,
130
+ `[AUTH_SCOPE]`, type ReCaptcha. A posted `profileId`, `entitySlug`/`entityId`, `permissions`,
131
+ `groups`, `expiresAt`, `source` or `publicKey` is dropped; `source` never changes the spend key.
132
+
133
+ **Token.** The manager signs it as usual: an `AUTHEN_TIMEFRAME` envelope of type `re-captcha` whose
134
+ `challenge` is the server-issued wrapped challenge (the spend key) and whose `credential` is the
135
+ `AUTH_SRV_KEY` record's id. The browser sends it as `Authorization: RE-CAPTCHA <token>`.
136
+
137
+ **Guard.** A route takes it with `guards: [RECAPTCHA_GUARD]` and `makeReCaptchaGuard()` registered
138
+ in a context holding the `AUTH_SRV_KEY` trusted record (public key is enough) and a shared
139
+ `AUTH_CACHE`. `reCaptchaTokenOf(ctx).inspect(req)` checks, without spending: envelope type, a TTL
140
+ of at most `AUTHEN_TIMEFRAME`, signature and expiry, the auth record's stamp, type ReCaptcha, role
141
+ Guest, `GUEST_ID`, a non-empty challenge. The guard then spends it — an atomic create-once of the
142
+ challenge in `AUTH_CACHE` (Redis `SET NX`), the same key a bearer exchange and the integrated IAM's
143
+ finalizer claim, so a token is spent once across the platform. A replay, or any failed check, is
144
+ 401. `req.auth` becomes a guest with `token: ''` and `expiresAt` = the token's expiry. Use
145
+ `inspect` for a pre-parse check (before a large body is read); the route still needs the guard.
146
+
147
+ **Never a session.** `AuthService.authenticate` (the dispatcher's bearer exchange) refuses a
148
+ credential whose envelope or `type` is ReCaptcha (`AuthenFailed('guest')`) before spending it. A
149
+ service that judges manager tokens itself (a finalizer) must check the method it expects — the
150
+ token's type and its challenge's envelope type — not just the signature, since one key signs every
151
+ method's token.
152
+
153
+ ## Rules
37
154
 
38
- - Backend context registers `appendAuthService(context)` before identity resources and product-specific gate services.
39
- - `AUTH_CACHE` must be registered as a Redis resource when the backend context does not rely on the default `server-app` setup.
40
- - `server-auth` verifies bearer tokens and populates `req.auth`; it does not decide product ownership or permissions by itself.
41
- - Pair this package with `@owlmeans/server-auth-identity` when an external provider such as Google should map into local account/profile/credentials records.
42
- - Pair it with `@owlmeans/entrypoint` gates for authorization, and keep handler-level `entityId` checks as a second line of defense.
155
+ - The guard verifies a bearer token and populates `req.auth`. It decides nothing about ownership or
156
+ permissions — pair it with `@owlmeans/entrypoint` gates, and keep a handler-level organization
157
+ check as a second line of defence.
158
+ - `AUTH_CACHE` is the anti-replay store: the manager burns each decoded challenge into it as a
159
+ create-once record with `AUTHEN_TIMEFRAME` TTL. `appendAuthService` registers a **static**
160
+ (in-process) resource when the context has none, which is correct for a single replica only —
161
+ register a Redis resource under the same alias before calling it in any scaled deployment.
162
+ - A plugin's `init` must return a challenge that is unique per request. A challenge that repeats
163
+ across independent attempts collides in `AUTH_CACHE` and surfaces as `AuthenFailed('challenge')`.
164
+ - Bearers issued by this service carry an absolute seven-day expiry and an opaque session id. In a
165
+ context with `AUTH_SESSION_MANAGER`, the guard rejects an absent, expired, pending or revoked
166
+ session and re-signs fresh profile claims after a registry revision. Registry or identity-store
167
+ failure is `AuthUnavailable` (503), never a false 401/logout.
168
+ - The session registry (`AUTH_SESSION_MANAGER`) is `@owlmeans/server-auth-session`'s, not exported
169
+ here; `appendAuthService` installs its memory manager only as a single-process default. A
170
+ central or multi-replica issuer registers `appendRedisAuthSessionManager(context)` before it;
171
+ the manager is the authority that fences, refreshes or revokes an organization profile's sessions.
172
+ - The manager canonicalizes the organization entity: whatever slug (current, retired, or the frozen
173
+ key) a plugin leaves on `credential.entitySlug` is resolved through `ENTITY_RESOLVER` and replaced
174
+ with the current slug before the envelope is signed. An unresolvable value throws
175
+ `AuthenFailed('entity')`. Where no resolver is registered the value is passed through untouched.
176
+ - Pair this package with `@owlmeans/server-auth-identity` when an external provider (Google, OIDC,
177
+ email OTP) must map onto local account/profile/credential records.
178
+ - A reCAPTCHA token is a guest token: only `makeReCaptchaGuard` accepts it, once; the bearer
179
+ exchange refuses it (see "reCAPTCHA guests").
43
180
 
44
181
  ## Depends On
45
182
 
46
- - `@owlmeans/auth`, `@owlmeans/auth-common`
47
- - `@owlmeans/server-entrypoint`, `@owlmeans/server-context`
48
- - `@owlmeans/basic-keys` — Ed25519 verification
183
+ - `@owlmeans/auth`, `@owlmeans/auth-common` — types, aliases, `trust()`, `extractAuthToken`
184
+ - `@owlmeans/basic-envelope`, `@owlmeans/basic-keys` — envelope signing and Ed25519 verification
185
+ - `@owlmeans/server-context`, `@owlmeans/server-entrypoint`, `@owlmeans/server-api`
186
+ - `@owlmeans/config` — the `TRUSTED` config resource
187
+ - `@owlmeans/static-resource` — the default `AUTH_CACHE` backing