@aooth/arbac-moost 0.1.8 → 0.1.9

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.
@@ -1,4 +1,4 @@
1
- import { t as AoothArbacUserCredentials } from "../user-B5vN7nVU.mjs";
1
+ import { t as AoothArbacUserCredentials } from "../user-Dzu_08g0.mjs";
2
2
  import { r as AoothArbacClaims, t as ArbacUserProvider } from "../user.provider-CKPMp3G8.mjs";
3
3
  import { TAtscriptAnnotatedType } from "@atscript/typescript/utils";
4
4
 
@@ -141,4 +141,43 @@ declare function validateAttenuationTargets(credType: TAtscriptAnnotatedType, va
141
141
  */
142
142
  declare function extractAttenuation(credType: TAtscriptAnnotatedType, record: object | null | undefined): AoothArbacClaims | undefined;
143
143
  //#endregion
144
- export { AoothArbacUserCredentials, type ArbacAttenuationSpec, type ArbacUserTable, AtscriptArbacUserProvider, extractAttenuation, getArbacAttenuationSpec, validateAttenuationTargets };
144
+ //#region src/atscript/handle-spec.d.ts
145
+ /**
146
+ * Resolved login/recovery HANDLE fields for a user credential model, discovered
147
+ * from the `@aooth.user.*` annotations (registered by `arbacPlugin`). Computed
148
+ * once per `TAtscriptAnnotatedType` and cached.
149
+ *
150
+ * - `emailField` — the field annotated `@aooth.user.email` **and** carrying a
151
+ * `@db.index.unique` index. `undefined` when no field is annotated, or when
152
+ * the annotated field lacks a unique index (the handle is then DISABLED — see
153
+ * `warnings`).
154
+ * - `phoneField` — same, for `@aooth.user.phone`.
155
+ * - `handleFields` — the enabled handle field names in resolution order (email,
156
+ * then phone; disabled handles omitted). Pass this straight to a `UserStore`
157
+ * (`UsersStoreAtscriptDb` / `UserStoreMemory`) as its `handleFields` — the
158
+ * store stays name-agnostic; this spec owns the email/phone semantics.
159
+ * - `warnings` — non-fatal misconfig notes (an annotated field with no unique
160
+ * index → that handle is disabled, not fatal). The wiring layer should log
161
+ * these at boot. Ambiguity (more than one field per role) is fatal and throws.
162
+ *
163
+ * A handle MUST be unique-when-present because `findByHandle` resolves a handle
164
+ * to AT MOST one row; a non-unique handle would resolve to an arbitrary one of
165
+ * several rows (an account-takeover footgun). That is why the unique index is
166
+ * the gate, and why a missing index disables rather than silently accepts.
167
+ */
168
+ interface AoothUserHandleSpec {
169
+ emailField: string | undefined;
170
+ phoneField: string | undefined;
171
+ handleFields: string[];
172
+ warnings: string[];
173
+ }
174
+ /**
175
+ * Walk a user model's `@aooth.user.*` annotations into a cached
176
+ * {@link AoothUserHandleSpec}. Mirrors {@link getArbacAttenuationSpec}:
177
+ * structural, computed once, fail-loud on ambiguity. A model with no
178
+ * `@aooth.user.*` field resolves to all-`undefined` handles (email/phone login
179
+ * is simply unavailable — graceful degradation, not an error).
180
+ */
181
+ declare function getAoothUserHandleSpec(userType: TAtscriptAnnotatedType): AoothUserHandleSpec;
182
+ //#endregion
183
+ export { AoothArbacUserCredentials, type AoothUserHandleSpec, type ArbacAttenuationSpec, type ArbacUserTable, AtscriptArbacUserProvider, extractAttenuation, getAoothUserHandleSpec, getArbacAttenuationSpec, validateAttenuationTargets };
@@ -1,5 +1,5 @@
1
1
  import { r as __decorate, t as ArbacUserProvider } from "../user.provider-BiM5P8fl.mjs";
2
- import { t as AoothArbacUserCredentials } from "../user-B5vN7nVU.mjs";
2
+ import { t as AoothArbacUserCredentials } from "../user-Dzu_08g0.mjs";
3
3
  import { defineWook, key } from "@wooksjs/event-core";
4
4
  import { Injectable } from "moost";
5
5
  //#region src/atscript/role-list.ts
@@ -27,7 +27,7 @@ function __decorateMetadata(k, v) {
27
27
  }
28
28
  //#endregion
29
29
  //#region src/atscript/auto-provider.ts
30
- const specCache$1 = /* @__PURE__ */ new WeakMap();
30
+ const specCache$2 = /* @__PURE__ */ new WeakMap();
31
31
  /**
32
32
  * Resolve the identifier field on an object type using the three-step chain
33
33
  * documented on `ArbacExtractSpec.userIdField`. Used for the user type AND
@@ -66,7 +66,7 @@ function resolveIdentifierField(type) {
66
66
  return metaId;
67
67
  }
68
68
  function getArbacExtractSpec(type) {
69
- const cached = specCache$1.get(type);
69
+ const cached = specCache$2.get(type);
70
70
  if (cached !== void 0) return cached;
71
71
  const spec = {
72
72
  userIdField: void 0,
@@ -75,7 +75,7 @@ function getArbacExtractSpec(type) {
75
75
  };
76
76
  const def = type.type;
77
77
  if (def.kind !== "object") {
78
- specCache$1.set(type, spec);
78
+ specCache$2.set(type, spec);
79
79
  return spec;
80
80
  }
81
81
  const roleCandidates = [];
@@ -106,7 +106,7 @@ function getArbacExtractSpec(type) {
106
106
  };
107
107
  }
108
108
  spec.userIdField = resolveIdentifierField(type);
109
- specCache$1.set(type, spec);
109
+ specCache$2.set(type, spec);
110
110
  return spec;
111
111
  }
112
112
  /**
@@ -236,14 +236,14 @@ let AtscriptArbacUserProvider = class AtscriptArbacUserProvider extends ArbacUse
236
236
  AtscriptArbacUserProvider = __decorate([Injectable(), __decorateMetadata("design:paramtypes", [Object, Object])], AtscriptArbacUserProvider);
237
237
  //#endregion
238
238
  //#region src/atscript/attenuation-extract.ts
239
- const specCache = /* @__PURE__ */ new WeakMap();
239
+ const specCache$1 = /* @__PURE__ */ new WeakMap();
240
240
  /**
241
241
  * Walk a credential model's `@arbac.attenuate.*` annotations into a cached
242
242
  * {@link ArbacAttenuationSpec}. Mirrors the user-side `getArbacExtractSpec`:
243
243
  * structural, computed once, fail-loud on an ambiguous (multiple) role field.
244
244
  */
245
245
  function getArbacAttenuationSpec(credType) {
246
- const cached = specCache.get(credType);
246
+ const cached = specCache$1.get(credType);
247
247
  if (cached !== void 0) return cached;
248
248
  const spec = {
249
249
  roleField: void 0,
@@ -251,7 +251,7 @@ function getArbacAttenuationSpec(credType) {
251
251
  };
252
252
  const def = credType.type;
253
253
  if (def.kind !== "object") {
254
- specCache.set(credType, spec);
254
+ specCache$1.set(credType, spec);
255
255
  return spec;
256
256
  }
257
257
  const roleCandidates = [];
@@ -266,7 +266,7 @@ function getArbacAttenuationSpec(credType) {
266
266
  }
267
267
  if (roleCandidates.length > 1) throw new Error(`getArbacAttenuationSpec: multiple @arbac.attenuate.role fields declared (${roleCandidates.join(", ")}). Exactly one assumed-role source is supported — drop @arbac.attenuate.role from all but the canonical field.`);
268
268
  if (roleCandidates.length === 1) spec.roleField = roleCandidates[0];
269
- specCache.set(credType, spec);
269
+ specCache$1.set(credType, spec);
270
270
  return spec;
271
271
  }
272
272
  /**
@@ -330,4 +330,67 @@ function extractAttenuation(credType, record) {
330
330
  return out;
331
331
  }
332
332
  //#endregion
333
- export { AoothArbacUserCredentials, AtscriptArbacUserProvider, extractAttenuation, getArbacAttenuationSpec, validateAttenuationTargets };
333
+ //#region src/atscript/handle-spec.ts
334
+ const specCache = /* @__PURE__ */ new WeakMap();
335
+ /** A `@db.index.unique` annotation is a non-empty `(string | true)[]`. */
336
+ function hasUniqueIndex(md) {
337
+ const unique = md.get("db.index.unique");
338
+ return Array.isArray(unique) && unique.length > 0;
339
+ }
340
+ /**
341
+ * Resolve a single handle field for one role: fail loud on ambiguity (more than
342
+ * one annotated field — there is no canonical choice), and warn-and-disable when
343
+ * the sole annotated field lacks a unique index.
344
+ */
345
+ function resolveHandleField(role, annotation, candidates, warnings) {
346
+ if (candidates.length === 0) return void 0;
347
+ if (candidates.length > 1) throw new Error(`getAoothUserHandleSpec: multiple ${annotation} fields declared (${candidates.map((c) => c.field).join(", ")}). Exactly one ${role} login handle is supported — drop ${annotation} from all but the canonical field.`);
348
+ const { field, md } = candidates[0];
349
+ if (!hasUniqueIndex(md)) {
350
+ warnings.push(`${annotation} on field "${field}" has no @db.index.unique — a login handle must resolve to at most one row, so the ${role} handle is DISABLED (login/recovery by ${role} unavailable). Add @db.index.unique to the field to enable it.`);
351
+ return;
352
+ }
353
+ return field;
354
+ }
355
+ /**
356
+ * Walk a user model's `@aooth.user.*` annotations into a cached
357
+ * {@link AoothUserHandleSpec}. Mirrors {@link getArbacAttenuationSpec}:
358
+ * structural, computed once, fail-loud on ambiguity. A model with no
359
+ * `@aooth.user.*` field resolves to all-`undefined` handles (email/phone login
360
+ * is simply unavailable — graceful degradation, not an error).
361
+ */
362
+ function getAoothUserHandleSpec(userType) {
363
+ const cached = specCache.get(userType);
364
+ if (cached !== void 0) return cached;
365
+ const spec = {
366
+ emailField: void 0,
367
+ phoneField: void 0,
368
+ handleFields: [],
369
+ warnings: []
370
+ };
371
+ const def = userType.type;
372
+ if (def.kind !== "object") {
373
+ specCache.set(userType, spec);
374
+ return spec;
375
+ }
376
+ const emailCandidates = [];
377
+ const phoneCandidates = [];
378
+ for (const [fieldName, fieldType] of def.props) {
379
+ const md = fieldType.metadata;
380
+ if (md.get("aooth.user.email")) emailCandidates.push({
381
+ field: fieldName,
382
+ md
383
+ });
384
+ if (md.get("aooth.user.phone")) phoneCandidates.push({
385
+ field: fieldName,
386
+ md
387
+ });
388
+ }
389
+ spec.emailField = resolveHandleField("email", "@aooth.user.email", emailCandidates, spec.warnings);
390
+ spec.phoneField = resolveHandleField("phone", "@aooth.user.phone", phoneCandidates, spec.warnings);
391
+ spec.handleFields = [spec.emailField, spec.phoneField].filter((f) => f !== void 0);
392
+ specCache.set(userType, spec);
393
+ return spec;
394
+ }
395
+ //#endregion
396
+ export { AoothArbacUserCredentials, AtscriptArbacUserProvider, extractAttenuation, getAoothUserHandleSpec, getArbacAttenuationSpec, validateAttenuationTargets };
package/dist/plugin.d.mts CHANGED
@@ -29,6 +29,16 @@ import { TAtscriptPlugin } from "@atscript/core";
29
29
  * key in the user model's `@arbac.attribute` keyspace (validated to exist at
30
30
  * boot). Multiple fields may each carry it, targeting different attrs.
31
31
  *
32
+ * This plugin also registers the `@aooth.user.*` identity-handle namespace
33
+ * (read by `getAoothUserHandleSpec`) so `.as` user models can mark their login
34
+ * handles name-agnostically:
35
+ *
36
+ * - `@aooth.user.email` — the field is the EMAIL login/recovery handle. Resolved
37
+ * by annotation (not by being literally named `email`). MUST carry
38
+ * `@db.index.unique` (unique-when-present); without it the handle is disabled
39
+ * with a warning. At most one per type.
40
+ * - `@aooth.user.phone` — the PHONE login/recovery handle, same contract.
41
+ *
32
42
  * Install in `atscript.config.ts`:
33
43
  *
34
44
  * ```ts
package/dist/plugin.mjs CHANGED
@@ -28,6 +28,16 @@ import { AnnotationSpec } from "@atscript/core";
28
28
  * key in the user model's `@arbac.attribute` keyspace (validated to exist at
29
29
  * boot). Multiple fields may each carry it, targeting different attrs.
30
30
  *
31
+ * This plugin also registers the `@aooth.user.*` identity-handle namespace
32
+ * (read by `getAoothUserHandleSpec`) so `.as` user models can mark their login
33
+ * handles name-agnostically:
34
+ *
35
+ * - `@aooth.user.email` — the field is the EMAIL login/recovery handle. Resolved
36
+ * by annotation (not by being literally named `email`). MUST carry
37
+ * `@db.index.unique` (unique-when-present); without it the handle is disabled
38
+ * with a warning. At most one per type.
39
+ * - `@aooth.user.phone` — the PHONE login/recovery handle, same contract.
40
+ *
31
41
  * Install in `atscript.config.ts`:
32
42
  *
33
43
  * ```ts
@@ -39,40 +49,54 @@ function arbacPlugin() {
39
49
  return {
40
50
  name: "aoothjs-arbac",
41
51
  config() {
42
- return { annotations: { arbac: {
43
- role: new AnnotationSpec({
44
- description: "Marks this field as THE source of role identifiers for ARBAC evaluation. Two shapes are supported: inline (string | string[]) or @db.rel.from nav prop. Exactly one @arbac.role field per type — multiple declarations throw at boot.",
45
- nodeType: ["prop"],
46
- multiple: false
47
- }),
48
- attribute: new AnnotationSpec({
49
- description: "Marks this field as a user attribute used by ARBAC scope evaluation. The field name becomes the attribute key. Multiple fields are merged.",
50
- nodeType: ["prop"],
51
- multiple: false
52
- }),
53
- userId: new AnnotationSpec({
54
- description: "Overrides which field provides the user identifier for ARBAC. Resolution chain: @arbac.userId → @db.table.preferredId.uniqueIndex field → @meta.id.",
55
- nodeType: ["prop"],
56
- multiple: false
57
- }),
58
- attenuate: {
52
+ return { annotations: {
53
+ arbac: {
59
54
  role: new AnnotationSpec({
60
- description: "Marks the credential field holding the assumed-role SUBSET (string[]) for restrict-only ARBAC attenuation. Intersected with the user's roles (fail-closed). Exactly one @arbac.attenuate.role field per type — multiple declarations throw at boot.",
55
+ description: "Marks this field as THE source of role identifiers for ARBAC evaluation. Two shapes are supported: inline (string | string[]) or @db.rel.from nav prop. Exactly one @arbac.role field per type — multiple declarations throw at boot.",
56
+ nodeType: ["prop"],
57
+ multiple: false
58
+ }),
59
+ attribute: new AnnotationSpec({
60
+ description: "Marks this field as a user attribute used by ARBAC scope evaluation. The field name becomes the attribute key. Multiple fields are merged.",
61
+ nodeType: ["prop"],
62
+ multiple: false
63
+ }),
64
+ userId: new AnnotationSpec({
65
+ description: "Overrides which field provides the user identifier for ARBAC. Resolution chain: @arbac.userId → @db.table.preferredId.uniqueIndex field → @meta.id.",
66
+ nodeType: ["prop"],
67
+ multiple: false
68
+ }),
69
+ attenuate: {
70
+ role: new AnnotationSpec({
71
+ description: "Marks the credential field holding the assumed-role SUBSET (string[]) for restrict-only ARBAC attenuation. Intersected with the user's roles (fail-closed). Exactly one @arbac.attenuate.role field per type — multiple declarations throw at boot.",
72
+ nodeType: ["prop"],
73
+ multiple: false
74
+ }),
75
+ attr: new AnnotationSpec({
76
+ description: "Marks a credential field whose value narrows the named USER attribute for restrict-only ARBAC attenuation. The argument is the target key in the user model's @arbac.attribute keyspace (validated to exist at boot). Multiple fields may each carry it, targeting different attrs.",
77
+ nodeType: ["prop"],
78
+ multiple: false,
79
+ argument: {
80
+ name: "userAttr",
81
+ type: "string",
82
+ description: "Target user-attribute key (a field annotated @arbac.attribute on the user model)."
83
+ }
84
+ })
85
+ }
86
+ },
87
+ aooth: { user: {
88
+ email: new AnnotationSpec({
89
+ description: "Marks this field as the EMAIL login/recovery handle. The framework resolves the field by this annotation (name-agnostic) for findByHandle / recovery / signup. The field MUST carry @db.index.unique (unique-when-present) — a handle must resolve to at most one row; without a unique index the email handle is DISABLED with a warning. At most one @aooth.user.email field per type — multiple declarations throw at boot.",
61
90
  nodeType: ["prop"],
62
91
  multiple: false
63
92
  }),
64
- attr: new AnnotationSpec({
65
- description: "Marks a credential field whose value narrows the named USER attribute for restrict-only ARBAC attenuation. The argument is the target key in the user model's @arbac.attribute keyspace (validated to exist at boot). Multiple fields may each carry it, targeting different attrs.",
93
+ phone: new AnnotationSpec({
94
+ description: "Marks this field as the PHONE login/recovery handle. Same resolution + unique-index contract as @aooth.user.email (disabled with a warning when the field lacks @db.index.unique). At most one @aooth.user.phone field per type multiple throw at boot.",
66
95
  nodeType: ["prop"],
67
- multiple: false,
68
- argument: {
69
- name: "userAttr",
70
- type: "string",
71
- description: "Target user-attribute key (a field annotated @arbac.attribute on the user model)."
72
- }
96
+ multiple: false
73
97
  })
74
- }
75
- } } };
98
+ } }
99
+ } };
76
100
  }
77
101
  };
78
102
  }
@@ -0,0 +1,15 @@
1
+ import { defineAnnotatedType, throwFeatureDisabled } from "@atscript/typescript/utils";
2
+ import "@aooth/user/atscript-db/model.as";
3
+ //#region src/atscript/models/user.as
4
+ var AoothArbacUserCredentials = class {
5
+ static __is_atscript_annotated_type = true;
6
+ static type = {};
7
+ static metadata = /* @__PURE__ */ new Map();
8
+ static id = "AoothArbacUserCredentials";
9
+ static toJsonSchema() {
10
+ throwFeatureDisabled("JSON Schema", "jsonSchema", "emit.jsonSchema");
11
+ }
12
+ };
13
+ defineAnnotatedType("object", AoothArbacUserCredentials).prop("id", defineAnnotatedType().designType("string").tags("string").annotate("meta.id", true).annotate("db.default.uuid", true).$type).prop("username", defineAnnotatedType().designType("string").tags("string").annotate("db.index.unique", "username_idx", true).$type).prop("version", defineAnnotatedType().designType("number").tags("int", "number").annotate("db.column.version", true).annotate("expect.int", true).$type).prop("password", defineAnnotatedType("object").prop("hash", defineAnnotatedType().designType("string").tags("string").$type).prop("history", defineAnnotatedType("array").of(defineAnnotatedType().designType("string").tags("string").$type).$type).prop("lastChanged", defineAnnotatedType().designType("number").tags("timestamp", "number").annotate("expect.int", true).$type).prop("isInitial", defineAnnotatedType().designType("boolean").tags("boolean").$type).annotate("db.patch.strategy", "merge").$type).prop("account", defineAnnotatedType("object").prop("active", defineAnnotatedType().designType("boolean").tags("boolean").$type).prop("locked", defineAnnotatedType().designType("boolean").tags("boolean").$type).prop("lockReason", defineAnnotatedType().designType("string").tags("string").$type).prop("lockEnds", defineAnnotatedType().designType("number").tags("timestamp", "number").annotate("expect.int", true).$type).prop("failedLoginAttempts", defineAnnotatedType().designType("number").tags("number").$type).prop("lastLogin", defineAnnotatedType().designType("number").tags("timestamp", "number").annotate("expect.int", true).$type).prop("pendingInvitation", defineAnnotatedType().designType("boolean").tags("boolean").optional().$type).annotate("db.patch.strategy", "merge").$type).prop("mfa", defineAnnotatedType("object").prop("methods", defineAnnotatedType("array").of(defineAnnotatedType("object").prop("name", defineAnnotatedType().designType("string").tags("string").$type).prop("confirmed", defineAnnotatedType().designType("boolean").tags("boolean").$type).prop("value", defineAnnotatedType().designType("string").tags("string").$type).prop("lastUsedWindow", defineAnnotatedType().designType("number").tags("int", "number").annotate("expect.int", true).optional().$type).$type).$type).prop("defaultMethod", defineAnnotatedType().designType("string").tags("string").$type).prop("autoSend", defineAnnotatedType().designType("boolean").tags("boolean").$type).annotate("db.patch.strategy", "merge").$type).prop("trustedDevices", defineAnnotatedType("array").of(defineAnnotatedType("object").prop("token", defineAnnotatedType().designType("string").tags("string").$type).prop("ip", defineAnnotatedType().designType("string").tags("string").optional().$type).prop("issuedAt", defineAnnotatedType().designType("number").tags("timestamp", "number").annotate("expect.int", true).$type).prop("expiresAt", defineAnnotatedType().designType("number").tags("timestamp", "number").annotate("expect.int", true).$type).prop("name", defineAnnotatedType().designType("string").tags("string").optional().$type).$type).annotate("db.patch.strategy", "merge").optional().$type).prop("roles", defineAnnotatedType("array").of(defineAnnotatedType().designType("string").tags("string").$type).annotate("arbac.role", true).$type);
14
+ //#endregion
15
+ export { AoothArbacUserCredentials as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aooth/arbac-moost",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Moost RBAC integration for aoothjs (migrated from @moostjs/arbac)",
5
5
  "keywords": [
6
6
  "abac",
@@ -60,27 +60,27 @@
60
60
  "access": "public"
61
61
  },
62
62
  "dependencies": {
63
- "@aooth/arbac": "0.1.8",
64
- "@aooth/arbac-core": "0.1.8",
65
- "@aooth/user": "0.1.8"
63
+ "@aooth/arbac": "0.1.9",
64
+ "@aooth/arbac-core": "0.1.9",
65
+ "@aooth/user": "0.1.9"
66
66
  },
67
67
  "devDependencies": {
68
- "@atscript/core": "^0.1.69",
69
- "@atscript/db": "^0.1.96",
70
- "@atscript/db-sql-tools": "^0.1.96",
71
- "@atscript/db-sqlite": "^0.1.96",
72
- "@atscript/moost-db": "^0.1.96",
73
- "@atscript/typescript": "^0.1.69",
68
+ "@atscript/core": "^0.1.70",
69
+ "@atscript/db": "^0.1.97",
70
+ "@atscript/db-sql-tools": "^0.1.97",
71
+ "@atscript/db-sqlite": "^0.1.97",
72
+ "@atscript/moost-db": "^0.1.97",
73
+ "@atscript/typescript": "^0.1.70",
74
74
  "@moostjs/event-http": "^0.6.23",
75
75
  "@types/better-sqlite3": "^7.6.13",
76
76
  "@uniqu/core": "^0.1.6",
77
77
  "better-sqlite3": "^12.6.2",
78
- "unplugin-atscript": "^0.1.69"
78
+ "unplugin-atscript": "^0.1.70"
79
79
  },
80
80
  "peerDependencies": {
81
- "@atscript/db": "^0.1.96",
82
- "@atscript/moost-db": "^0.1.96",
83
- "@atscript/typescript": "^0.1.69",
81
+ "@atscript/db": "^0.1.97",
82
+ "@atscript/moost-db": "^0.1.97",
83
+ "@atscript/typescript": "^0.1.70",
84
84
  "@moostjs/event-http": "^0.6.23",
85
85
  "@wooksjs/event-core": "^0.7.17",
86
86
  "@wooksjs/event-http": "^0.7.17",
@@ -1,15 +0,0 @@
1
- import { defineAnnotatedType, throwFeatureDisabled } from "@atscript/typescript/utils";
2
- import "@aooth/user/atscript-db/model.as";
3
- //#region src/atscript/models/user.as
4
- var AoothArbacUserCredentials = class {
5
- static __is_atscript_annotated_type = true;
6
- static type = {};
7
- static metadata = /* @__PURE__ */ new Map();
8
- static id = "AoothArbacUserCredentials";
9
- static toJsonSchema() {
10
- throwFeatureDisabled("JSON Schema", "jsonSchema", "emit.jsonSchema");
11
- }
12
- };
13
- defineAnnotatedType("object", AoothArbacUserCredentials).prop("id", defineAnnotatedType().designType("string").tags("string").annotate("meta.id", true).annotate("db.default.uuid", true).$type).prop("username", defineAnnotatedType().designType("string").tags("string").annotate("db.index.unique", "username_idx", true).$type).prop("email", defineAnnotatedType().designType("string").tags("string").annotate("db.index.unique", "email_idx", true).optional().$type).prop("version", defineAnnotatedType().designType("number").tags("int", "number").annotate("db.column.version", true).annotate("expect.int", true).$type).prop("password", defineAnnotatedType("object").prop("hash", defineAnnotatedType().designType("string").tags("string").$type).prop("history", defineAnnotatedType("array").of(defineAnnotatedType().designType("string").tags("string").$type).$type).prop("lastChanged", defineAnnotatedType().designType("number").tags("timestamp", "number").annotate("expect.int", true).$type).prop("isInitial", defineAnnotatedType().designType("boolean").tags("boolean").$type).annotate("db.patch.strategy", "merge").$type).prop("account", defineAnnotatedType("object").prop("active", defineAnnotatedType().designType("boolean").tags("boolean").$type).prop("locked", defineAnnotatedType().designType("boolean").tags("boolean").$type).prop("lockReason", defineAnnotatedType().designType("string").tags("string").$type).prop("lockEnds", defineAnnotatedType().designType("number").tags("timestamp", "number").annotate("expect.int", true).$type).prop("failedLoginAttempts", defineAnnotatedType().designType("number").tags("number").$type).prop("lastLogin", defineAnnotatedType().designType("number").tags("timestamp", "number").annotate("expect.int", true).$type).prop("pendingInvitation", defineAnnotatedType().designType("boolean").tags("boolean").optional().$type).annotate("db.patch.strategy", "merge").$type).prop("mfa", defineAnnotatedType("object").prop("methods", defineAnnotatedType("array").of(defineAnnotatedType("object").prop("name", defineAnnotatedType().designType("string").tags("string").$type).prop("confirmed", defineAnnotatedType().designType("boolean").tags("boolean").$type).prop("value", defineAnnotatedType().designType("string").tags("string").$type).prop("lastUsedWindow", defineAnnotatedType().designType("number").tags("int", "number").annotate("expect.int", true).optional().$type).$type).$type).prop("defaultMethod", defineAnnotatedType().designType("string").tags("string").$type).prop("autoSend", defineAnnotatedType().designType("boolean").tags("boolean").$type).annotate("db.patch.strategy", "merge").$type).prop("trustedDevices", defineAnnotatedType("array").of(defineAnnotatedType("object").prop("token", defineAnnotatedType().designType("string").tags("string").$type).prop("ip", defineAnnotatedType().designType("string").tags("string").optional().$type).prop("issuedAt", defineAnnotatedType().designType("number").tags("timestamp", "number").annotate("expect.int", true).$type).prop("expiresAt", defineAnnotatedType().designType("number").tags("timestamp", "number").annotate("expect.int", true).$type).prop("name", defineAnnotatedType().designType("string").tags("string").optional().$type).$type).annotate("db.patch.strategy", "merge").optional().$type).prop("roles", defineAnnotatedType("array").of(defineAnnotatedType().designType("string").tags("string").$type).annotate("arbac.role", true).$type);
14
- //#endregion
15
- export { AoothArbacUserCredentials as t };