@owlmeans/server-auth-identity 0.1.18-rc.3 → 0.1.18-rc.31
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 +229 -57
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/server-auth-identity/SKILL.md +191 -74
- package/build/consts.d.ts +4 -0
- package/build/consts.d.ts.map +1 -1
- package/build/consts.js +7 -0
- package/build/consts.js.map +1 -1
- package/build/events.d.ts +9 -0
- package/build/events.d.ts.map +1 -0
- package/build/events.js +29 -0
- package/build/events.js.map +1 -0
- package/build/helper.d.ts.map +1 -1
- package/build/helper.js +13 -1
- package/build/helper.js.map +1 -1
- package/build/index.d.ts +2 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -0
- package/build/index.js.map +1 -1
- package/build/resolver.d.ts +3 -0
- package/build/resolver.d.ts.map +1 -0
- package/build/resolver.js +133 -0
- package/build/resolver.js.map +1 -0
- package/build/resource.d.ts +11 -1
- package/build/resource.d.ts.map +1 -1
- package/build/resource.js +30 -4
- package/build/resource.js.map +1 -1
- package/build/service.d.ts.map +1 -1
- package/build/service.js +130 -25
- package/build/service.js.map +1 -1
- package/build/types.d.ts +78 -4
- package/build/types.d.ts.map +1 -1
- package/package.json +10 -9
- package/src/consts.ts +8 -0
- package/src/events.ts +39 -0
- package/src/helper.ts +13 -1
- package/src/index.ts +2 -0
- package/src/resolver.ts +165 -0
- package/src/resource.ts +36 -6
- package/src/service.ts +146 -28
- package/src/types.ts +82 -4
- package/tests/context.ts +98 -0
- package/tests/events.spec.ts +81 -0
- package/tests/linking.spec.ts +133 -0
- package/tsconfig.json +1 -1
package/README.md
CHANGED
|
@@ -1,97 +1,269 @@
|
|
|
1
1
|
# @owlmeans/server-auth-identity
|
|
2
2
|
|
|
3
|
-
Mongo-backed local identity
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
- Keeps external provider identity separate from local product identity and authorization scopes.
|
|
10
|
-
- Designed to work with `@owlmeans/server-auth`, `@owlmeans/server-oidc-rp`, and product-specific module gates.
|
|
3
|
+
The Mongo-backed local identity store behind provider logins. An application uses it when it owns
|
|
4
|
+
its users and organizations: a Google, OIDC, email-OTP or supervisor login is mapped onto one local
|
|
5
|
+
account, profile and credential, and the organization entity registry turns the slug on a token into
|
|
6
|
+
a stable entity id. It is not used where identity and authorization are delegated to an external IAM
|
|
7
|
+
whose grants decide access (use `@owlmeans/server-oidc-rp`'s guard and gate, or
|
|
8
|
+
`@owlmeans/server-iam`), and it does not verify bearer tokens (that is `@owlmeans/server-auth`).
|
|
11
9
|
|
|
12
10
|
## Installation
|
|
13
11
|
|
|
14
12
|
```bash
|
|
15
|
-
bun add @owlmeans/server-auth-identity
|
|
13
|
+
bun add @owlmeans/server-auth-identity@^0.1.18-rc.31
|
|
16
14
|
```
|
|
17
15
|
|
|
16
|
+
## Concepts
|
|
17
|
+
|
|
18
|
+
- **Organization entity (`OrgEntity`)** — the customer organization: `id` (stable `entityId`,
|
|
19
|
+
never on the wire), `slug` (renameable `entitySlug`, the only value a token carries),
|
|
20
|
+
`formerSlugs` that keep resolving after a rename, a frozen `iamKey`, and `names` minted once for
|
|
21
|
+
systems that cannot be renamed.
|
|
22
|
+
- **Account (`IdentityAccount`)** — one per person, matched on a verified email `name`.
|
|
23
|
+
- **Profile (`IdentityProfile`)** — one person inside one organization entity, with `role`,
|
|
24
|
+
`scopes` and optional `expiresAt`. The durable authorization record.
|
|
25
|
+
- **Credentials (`IdentityCredentials`)** — one provider link per profile, keyed by
|
|
26
|
+
`"{type}:{service}:{providerSub}"`.
|
|
27
|
+
- **Linking service** — `IdentityLinkingService` finds or creates the local identity for provider
|
|
28
|
+
profile details and returns an `AuthPayload`.
|
|
29
|
+
- **Entity resolver** — the `EntityResolverService` registered under `ENTITY_RESOLVER`. Registering
|
|
30
|
+
it tells the server boundary that this deployment has organizations.
|
|
31
|
+
- **Identity events** — `identityEvents(ctx)` returns the `IdentityEventsService`; its
|
|
32
|
+
`onEntityCreated` listeners run once per newly registered organization entity.
|
|
33
|
+
|
|
18
34
|
## Usage
|
|
19
35
|
|
|
20
|
-
Register
|
|
36
|
+
### Register in a context
|
|
37
|
+
|
|
38
|
+
Register after the Mongo service and `appendAuthService`. A dedicated db config under
|
|
39
|
+
`AUTH_IDENTITY_DB_ALIAS` scopes a collection prefix to the identity collections only.
|
|
21
40
|
|
|
22
|
-
```
|
|
23
|
-
|
|
41
|
+
```ts
|
|
42
|
+
// config.ts
|
|
43
|
+
import { AUTH_IDENTITY_DB_ALIAS, AUTH_IDENTITY_LINKING } from '@owlmeans/server-auth-identity'
|
|
24
44
|
|
|
25
|
-
|
|
45
|
+
cfg.dbs.push({
|
|
46
|
+
alias: AUTH_IDENTITY_DB_ALIAS,
|
|
47
|
+
service: MONGO_SERVICE,
|
|
48
|
+
host: process.env.MONGO_HOST!,
|
|
49
|
+
schema: 'my-app',
|
|
50
|
+
secret: process.env.MONGO_SECRET!,
|
|
51
|
+
resourcePrefix: 'my-app-', // -> my-app-account, my-app-profile, ...
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
// let the OIDC relying party link provider logins through this store
|
|
55
|
+
cfg.oidc.accountLinkingService = AUTH_IDENTITY_LINKING
|
|
26
56
|
```
|
|
27
57
|
|
|
28
|
-
|
|
58
|
+
```ts
|
|
59
|
+
// context.ts
|
|
60
|
+
import { appendAuthService } from '@owlmeans/server-auth'
|
|
61
|
+
import { appendAuthIdentityResources, AUTH_IDENTITY_DB_ALIAS } from '@owlmeans/server-auth-identity'
|
|
29
62
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
63
|
+
appendMongo<C, T>(context)
|
|
64
|
+
appendAuthService<C, T>(context)
|
|
65
|
+
appendAuthIdentityResources(context, AUTH_IDENTITY_DB_ALIAS)
|
|
66
|
+
context.registerService(makeMyAppGate())
|
|
67
|
+
```
|
|
33
68
|
|
|
34
|
-
|
|
69
|
+
### A product gate over profile scopes
|
|
35
70
|
|
|
36
|
-
|
|
71
|
+
```ts
|
|
72
|
+
import { createLazyService } from '@owlmeans/context'
|
|
73
|
+
import type { GateService } from '@owlmeans/entrypoint'
|
|
74
|
+
import { AuthForbidden } from '@owlmeans/auth'
|
|
75
|
+
import { entityKeyOf } from '@owlmeans/auth-common'
|
|
76
|
+
import { AUTH_IDENTITY_PROFILE } from '@owlmeans/server-auth-identity'
|
|
77
|
+
import type { IdentityProfileResource } from '@owlmeans/server-auth-identity'
|
|
78
|
+
|
|
79
|
+
export const makeMyAppGate = (alias: string = MY_APP_GATE): GateService => {
|
|
80
|
+
const service: GateService = createLazyService<GateService>(alias, {
|
|
81
|
+
assert: async (req, _, params) => {
|
|
82
|
+
await service.ready()
|
|
83
|
+
const ctx = service.assertCtx<Config, Context>()
|
|
84
|
+
|
|
85
|
+
const entityId = entityKeyOf(req)
|
|
86
|
+
if (req.auth == null || entityId == null) {
|
|
87
|
+
throw new AuthForbidden('auth')
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const profile = await ctx.resource<IdentityProfileResource>(AUTH_IDENTITY_PROFILE)
|
|
91
|
+
.load({ entityId, profileId: req.auth.profileId })
|
|
92
|
+
if (profile == null || (profile.expiresAt != null && new Date(profile.expiresAt) < new Date())) {
|
|
93
|
+
throw new AuthForbidden('profile')
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const scopes = req.auth.scopes ?? []
|
|
97
|
+
const required = params.map(param => param.replace(/\{entity\}/g, entityId))
|
|
98
|
+
if (!required.every(scope => scopes.includes('*') || scopes.includes(scope))) {
|
|
99
|
+
throw new AuthForbidden('permission')
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
return service
|
|
105
|
+
}
|
|
37
106
|
```
|
|
38
107
|
|
|
39
|
-
|
|
108
|
+
A protocol uses it with `{ guards: DEFAULT_GUARD, gate: { alias: MY_APP_GATE, params: ['my-app-project-{entity}'] } }`.
|
|
109
|
+
|
|
110
|
+
### Read an organization's members
|
|
40
111
|
|
|
41
|
-
```
|
|
112
|
+
```ts
|
|
113
|
+
import { handlers } from '@owlmeans/server-app'
|
|
114
|
+
import { requireEntityKey } from '@owlmeans/auth-common'
|
|
42
115
|
import { AUTH_IDENTITY_PROFILE } from '@owlmeans/server-auth-identity'
|
|
43
116
|
import type { IdentityProfileResource } from '@owlmeans/server-auth-identity'
|
|
44
117
|
|
|
45
|
-
const
|
|
46
|
-
|
|
118
|
+
const api = handlers<Context>()
|
|
119
|
+
|
|
120
|
+
export const members = api.request(memberProtocols.list, async (request, context) => {
|
|
121
|
+
const { items } = await context.resource<IdentityProfileResource>(AUTH_IDENTITY_PROFILE)
|
|
122
|
+
.list({ entityId: requireEntityKey(request) }, { sort: [{ field: 'createdAt', order: 'desc' }] })
|
|
47
123
|
|
|
48
|
-
|
|
124
|
+
return items.map(({ profileId, role, name }) => ({ profileId, role, name }))
|
|
125
|
+
})
|
|
49
126
|
```
|
|
50
127
|
|
|
51
|
-
|
|
128
|
+
### Link a provider login
|
|
52
129
|
|
|
53
|
-
|
|
130
|
+
```ts
|
|
131
|
+
import { AUTH_IDENTITY_LINKING } from '@owlmeans/server-auth-identity'
|
|
132
|
+
import type { IdentityLinkingService } from '@owlmeans/server-auth-identity'
|
|
54
133
|
|
|
55
|
-
|
|
56
|
-
- `makeIdentityProfileResource(dbAlias?)` - local profile record with `entityId`, `role`, `scopes`, and optional expiry.
|
|
57
|
-
- `makeIdentityCredentialsResource(dbAlias?)` - provider credentials link record.
|
|
58
|
-
- `appendAuthIdentityResources(context, dbAlias?)` - registers all resources and `IdentityLinkingService`.
|
|
134
|
+
const linking = context.service<IdentityLinkingService>(AUTH_IDENTITY_LINKING)
|
|
59
135
|
|
|
60
|
-
|
|
136
|
+
const details = {
|
|
137
|
+
type: 'google-oauth', // the AuthenticationType
|
|
138
|
+
service: 'google', // the provider service alias
|
|
139
|
+
clientId: 'google', // the provider client this login came through
|
|
140
|
+
userId: providerSub, // the provider's subject claim
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Returning login: find the credential, then its profile.
|
|
144
|
+
let payload = await linking.getLinkedProfile(details)
|
|
145
|
+
// First login by this method: link it to the person's identity, registering one if new.
|
|
146
|
+
payload ??= await linking.linkProfile(details, { username: 'person@example.org' })
|
|
147
|
+
// payload: { type, role, userId, profileId, entitySlug, scopes }
|
|
148
|
+
```
|
|
61
149
|
|
|
62
|
-
|
|
63
|
-
- `AUTH_IDENTITY_PROFILE` - profile resource alias.
|
|
64
|
-
- `AUTH_IDENTITY_CREDENTIALS` - provider credentials resource alias.
|
|
65
|
-
- `AUTH_IDENTITY_LINKING` - linking service alias.
|
|
150
|
+
### Provision when an organization is created
|
|
66
151
|
|
|
67
|
-
|
|
152
|
+
```ts
|
|
153
|
+
import { identityEvents } from '@owlmeans/server-auth-identity'
|
|
154
|
+
|
|
155
|
+
// in makeContext, after appendAuthIdentityResources
|
|
156
|
+
identityEvents(context)?.onEntityCreated(async (event, ctx) => {
|
|
157
|
+
await ctx.service<PlanService>(PLAN_SERVICE).grantStarterPlan(event.entityId)
|
|
158
|
+
})
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The event carries `entityId`, `entitySlug`, `iamKey`, `accountId`, `profileId`, `username`, the
|
|
162
|
+
login `type` and `service`, and `createdAt`. It fires only when `linkProfile` registers a new
|
|
163
|
+
identity (including `force: true`) — never when a second sign-in method links to an identity that
|
|
164
|
+
exists. Listeners run in order and are awaited; one that throws is logged and never fails the
|
|
165
|
+
sign-in, so anything a listener provisions needs its own backfill.
|
|
68
166
|
|
|
69
|
-
|
|
70
|
-
- `IdentityProfile` - `Profile & ResourceRecord`; includes `profileId`, `userId?`, `role`, `entityId`, `scopes`, `expiresAt?`.
|
|
71
|
-
- `IdentityCredentials` - `AuthCredentials & ResourceRecord`; includes `profileId` and derived provider keys.
|
|
72
|
-
- `IdentityLinkingService` - `getLinkedProfile`, `linkProfile`, `linkCredentials`, `getOwnerProfiles`, `getOwnerCredentials`.
|
|
167
|
+
### Rename an organization and mint a durable name
|
|
73
168
|
|
|
74
|
-
|
|
169
|
+
```ts
|
|
170
|
+
import { ENTITY_RESOLVER, requireEntityKey } from '@owlmeans/auth-common'
|
|
171
|
+
import type { EntityResolverService } from '@owlmeans/auth-common'
|
|
75
172
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
- Credentials `credential`: `"service:{type}:{service}"`.
|
|
173
|
+
export const rename = api.body(organizationProtocols.rename, async ({ slug }, context, request) => {
|
|
174
|
+
const resolver = context.service<EntityResolverService>(ENTITY_RESOLVER)
|
|
175
|
+
const entity = await resolver.rename(requireEntityKey(request), slug) // old slug moves to formerSlugs
|
|
80
176
|
|
|
81
|
-
|
|
177
|
+
return { slug: entity.slug }
|
|
178
|
+
})
|
|
82
179
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
- `Resource.pick()` is destructive and deletes the matching record. Never use `pick()` for gate or handler reads; use `load()` or `list()`.
|
|
180
|
+
// read once, or mint and persist on first ask; later renames leave it alone
|
|
181
|
+
const namespace = await resolver.mintName(entityId, 'namespace', entity => `my-app-${entity.iamKey}`)
|
|
182
|
+
```
|
|
87
183
|
|
|
88
|
-
##
|
|
184
|
+
## API
|
|
185
|
+
|
|
186
|
+
### Functions
|
|
187
|
+
|
|
188
|
+
| Symbol | Kind | Purpose |
|
|
189
|
+
|---|---|---|
|
|
190
|
+
| `appendAuthIdentityResources(context, dbAlias?)` | function | Register the four resources, the linking service, the entity resolver and (unless one is registered) the identity-events service |
|
|
191
|
+
| `makeOrgEntityResource(dbAlias?)` | function | Mongo resource for `OrgEntity` |
|
|
192
|
+
| `makeIdentityAccountResource(dbAlias?)` | function | Mongo resource for `IdentityAccount` |
|
|
193
|
+
| `makeIdentityProfileResource(dbAlias?)` | function | Mongo resource for `IdentityProfile` |
|
|
194
|
+
| `makeIdentityCredentialsResource(dbAlias?)` | function | Mongo resource for `IdentityCredentials` |
|
|
195
|
+
| `makeIdentityLinkingService()` | function | The `IdentityLinkingService` implementation |
|
|
196
|
+
| `makeEntityResolverService(alias = ENTITY_RESOLVER)` | function | The `EntityResolverService` implementation, cached 30 s per resolved name |
|
|
197
|
+
| `makeIdentityEventsService(alias = AUTH_IDENTITY_EVENTS)` | function | The `IdentityEventsService` implementation (lazy) |
|
|
198
|
+
| `identityEvents(ctx, alias?)` | function | The registered events service, or `null` |
|
|
199
|
+
|
|
200
|
+
### Constants
|
|
201
|
+
|
|
202
|
+
| Symbol | Kind | Purpose |
|
|
203
|
+
|---|---|---|
|
|
204
|
+
| `AUTH_IDENTITY_ORG_ENTITY`, `AUTH_IDENTITY_ACCOUNT`, `AUTH_IDENTITY_PROFILE`, `AUTH_IDENTITY_CREDENTIALS` | const | Resource aliases (`'auth-identity:…'`), lookup keys only |
|
|
205
|
+
| `AUTH_IDENTITY_LINKING` | const | `'auth-identity:linking'` — linking service alias |
|
|
206
|
+
| `AUTH_IDENTITY_EVENTS` | const | `'auth-identity:events'` — identity-events service alias |
|
|
207
|
+
| `AUTH_IDENTITY_DB_ALIAS` | const | `'auth-identity'` — suggested db config alias |
|
|
208
|
+
| `AUTH_IDENTITY_ORG_ENTITY_COLLECTION`, `AUTH_IDENTITY_ACCOUNT_COLLECTION`, `AUTH_IDENTITY_PROFILE_COLLECTION`, `AUTH_IDENTITY_CREDENTIALS_COLLECTION` | const | Colon-free Mongo collection base names |
|
|
209
|
+
| `MAX_ENTITY_SLUG_ATTEMPTS` | const | `8` — word slugs tried before minting gives up |
|
|
210
|
+
| `LOGIN_SERVICE_PREFIX`, `EXTERNAL_KEY_DELIMITER` | const | `'service'` and `':'` — the derived-key grammar |
|
|
211
|
+
|
|
212
|
+
### Types
|
|
89
213
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
214
|
+
| Symbol | Kind | Purpose |
|
|
215
|
+
|---|---|---|
|
|
216
|
+
| `OrgEntity` | type | `id`, `slug`, `formerSlugs?`, `iamKey`, `names?`, `createdAt`, `updatedAt?` |
|
|
217
|
+
| `IdentityAccount` | type | `Profile` without `entitySlug`, plus `id`, `credential`, `entityId?` |
|
|
218
|
+
| `IdentityProfile` | type | `Profile` without `entitySlug`, plus `id`, `profileId`, `userId?`, `role`, `entityId?`, `expiresAt?` |
|
|
219
|
+
| `IdentityCredentials` | type | `AuthCredentials` + `profileId` |
|
|
220
|
+
| `IdentityLinkingService` | type | `getLinkedProfile`, `linkProfile`, `linkCredentials`, `unlinkCredentials`, `getOwnerProfiles`, `getOwnerCredentials` |
|
|
221
|
+
| `AccountMeta` | type | `{ username, force? }` |
|
|
222
|
+
| `IdentityEventsService` | type | `onEntityCreated(callback)`, `propagateEntityCreated(event)` |
|
|
223
|
+
| `EntityCreatedEvent`, `EntityCreatedCallback` | type | The entity-created payload; `(event, ctx) => Promise<void>` |
|
|
224
|
+
| `OrgEntityResource`, `IdentityAccountResource`, `IdentityProfileResource`, `IdentityCredentialsResource` | type | Typed `MongoResource` aliases |
|
|
225
|
+
| `IdentityConfig`, `IdentityContext` | type | Server config and context shapes |
|
|
226
|
+
| `GoogleUserInfo` | type | Google userinfo claims |
|
|
227
|
+
| `EmailIdentityArgs`, `EmailIdentityPayload`, `IdentityIamExtension` | type | Declaration-only seam; nothing in the package consumes them |
|
|
228
|
+
|
|
229
|
+
## Key derivation
|
|
230
|
+
|
|
231
|
+
- Account `credential` — a unique 16-character Base58 slug.
|
|
232
|
+
- Account / profile `entityId` — the `OrgEntity` id; a first registration creates the entity first.
|
|
233
|
+
- Profile `userId` — the account's Mongo id, a declared ObjectId reference.
|
|
234
|
+
- Profile `profileId` — `"{type}:{accountId}"`.
|
|
235
|
+
- Credentials `userId` — `"{type}:{service}:{providerSub}"`; unrelated to the profile's `userId`.
|
|
236
|
+
- Credentials / profile `credential` — `"service:{type}:{service}"`; only platform logins carry it.
|
|
237
|
+
|
|
238
|
+
## Common pitfalls
|
|
239
|
+
|
|
240
|
+
- `Resource.take()` deletes the record it returns. Use `load(where)` or `list(where)` in gates and
|
|
241
|
+
handlers, never `take()`.
|
|
242
|
+
- Query profiles and organization records by `entityId` from `requireEntityKey(request)` /
|
|
243
|
+
`entityKeyOf(request)`, never by the slug.
|
|
244
|
+
- Without the resolver `request.entity` stays undefined and consumers fall back to the slug — call
|
|
245
|
+
`appendAuthIdentityResources` (or register the resolver) in every service that serves organization
|
|
246
|
+
data.
|
|
247
|
+
- First-login profiles get `ALL_SCOPES` and `AuthRole.User`; narrow scopes where finer authorization
|
|
248
|
+
is needed.
|
|
249
|
+
- `linkProfile(details, { username, force: true })` always registers a new identity — use it only
|
|
250
|
+
when a separate identity is intended.
|
|
251
|
+
- Provisioning in an `onEntityCreated` listener is best-effort: a throwing listener is logged and the
|
|
252
|
+
sign-in succeeds, so reconcile what it provisions periodically.
|
|
253
|
+
- The resolver caches for 30 seconds, so a rename reaches other replicas within that window; the old
|
|
254
|
+
slug keeps resolving meanwhile.
|
|
255
|
+
- `rename` rejects a malformed slug and any slug an entity has ever answered to; `mintSlug` throws
|
|
256
|
+
`entity:slug-exhausted` after `MAX_ENTITY_SLUG_ATTEMPTS`.
|
|
257
|
+
|
|
258
|
+
## Related packages
|
|
259
|
+
|
|
260
|
+
- [`@owlmeans/server-auth`](../server-auth) — bearer verification; canonicalizes the slug through the resolver
|
|
261
|
+
- [`@owlmeans/auth-common`](../auth-common) — `EntityResolverService`, `ENTITY_RESOLVER`, `requireEntityKey`, `attachEntity`
|
|
262
|
+
- [`@owlmeans/auth`](../auth) — `AuthPayload`, `AuthRole`, `Profile`, errors
|
|
263
|
+
- [`@owlmeans/server-oidc-rp`](../server-oidc-rp) — calls the linking service during an OAuth callback
|
|
264
|
+
- [`@owlmeans/server-auth-otp`](../server-auth-otp) — email OTP plugin resolving users through the linking service
|
|
265
|
+
- [`@owlmeans/oidc`](../oidc) — `ProviderProfileDetails`
|
|
266
|
+
- [`@owlmeans/mongo-resource`](../mongo-resource) — the Mongo resource implementation
|
|
95
267
|
|
|
96
268
|
<!-- owlmeans:agent-guidance:start -->
|
|
97
269
|
## Agent guidance
|
|
@@ -101,7 +273,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
101
273
|
your project's skill store (`.agents/skills/`):
|
|
102
274
|
|
|
103
275
|
```sh
|
|
104
|
-
npx @owlmeans/agent-skills
|
|
276
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.31
|
|
105
277
|
```
|
|
106
278
|
|
|
107
279
|
The embedded files are version-matched to this package release. Do not edit them
|
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/server-auth-identity",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-
|
|
4
|
+
"version": "0.1.18-rc.31",
|
|
5
|
+
"generatedAt": "2026-09-21T21:54:22.942Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|