@aventara/access 0.0.0-stage → 1.0.0-rc.1

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 (248) hide show
  1. package/CHANGELOG.md +877 -0
  2. package/LICENSE +91 -0
  3. package/LICENSE-ADDITIONAL-PERMISSION.md +9 -0
  4. package/README.md +2536 -2
  5. package/dist/access/access-options.d.ts +74 -0
  6. package/dist/access/access-options.js +5 -0
  7. package/dist/access/access.error.d.ts +35 -0
  8. package/dist/access/access.error.js +11 -0
  9. package/dist/access/access.factory.d.ts +275 -0
  10. package/dist/access/access.factory.js +440 -0
  11. package/dist/access/better-auth.hardening.d.ts +120 -0
  12. package/dist/access/better-auth.hardening.js +420 -0
  13. package/dist/access/better-auth.loader.d.ts +67 -0
  14. package/dist/access/better-auth.loader.js +65 -0
  15. package/dist/access/better-auth.range.d.ts +9 -0
  16. package/dist/access/better-auth.range.js +28 -0
  17. package/dist/access/better-auth.require.d.ts +90 -0
  18. package/dist/access/better-auth.require.js +6 -0
  19. package/dist/access/better-auth.require.node.d.ts +7 -0
  20. package/dist/access/better-auth.require.node.js +52 -0
  21. package/dist/access/claims.mapper.d.ts +79 -0
  22. package/dist/access/claims.mapper.js +152 -0
  23. package/dist/access/key-set.cache.d.ts +10 -0
  24. package/dist/access/key-set.cache.js +63 -0
  25. package/dist/access/policies-block.checker.d.ts +64 -0
  26. package/dist/access/policies-block.checker.js +138 -0
  27. package/dist/access/principal.subject.d.ts +22 -0
  28. package/dist/access/principal.subject.js +89 -0
  29. package/dist/access/profile.policy.d.ts +74 -0
  30. package/dist/access/profile.policy.js +110 -0
  31. package/dist/access/request.state.d.ts +89 -0
  32. package/dist/access/request.state.js +266 -0
  33. package/dist/access/session.hooks.d.ts +114 -0
  34. package/dist/access/session.hooks.js +258 -0
  35. package/dist/access/token.verifier.d.ts +35 -0
  36. package/dist/access/token.verifier.js +69 -0
  37. package/dist/access-schema.d.ts +48 -0
  38. package/dist/access-schema.js +5 -0
  39. package/dist/access-warning.emitter.d.ts +4 -0
  40. package/dist/access-warning.emitter.js +24 -0
  41. package/dist/access.builder.d.ts +340 -0
  42. package/dist/access.builder.js +75 -0
  43. package/dist/access.engine.d.ts +155 -0
  44. package/dist/access.engine.js +477 -0
  45. package/dist/audit/audit-event.d.ts +135 -0
  46. package/dist/audit/audit-event.js +8 -0
  47. package/dist/audit/audit.log.d.ts +122 -0
  48. package/dist/audit/audit.log.js +345 -0
  49. package/dist/audit/audit.schema.d.ts +143 -0
  50. package/dist/audit/audit.schema.js +50 -0
  51. package/dist/auth/index.d.ts +12 -0
  52. package/dist/auth/index.js +2 -0
  53. package/dist/aventara-where.translator.d.ts +19 -0
  54. package/dist/aventara-where.translator.js +87 -0
  55. package/dist/beacon/beacon.check.d.ts +59 -0
  56. package/dist/beacon/beacon.check.js +128 -0
  57. package/dist/beacon/beacon.schema.d.ts +41 -0
  58. package/dist/beacon/beacon.schema.js +48 -0
  59. package/dist/beacon/beacon.store.d.ts +29 -0
  60. package/dist/beacon/beacon.store.js +78 -0
  61. package/dist/better-auth/access.client-plugin.d.ts +75 -0
  62. package/dist/better-auth/access.client-plugin.js +133 -0
  63. package/dist/better-auth/access.plugin.d.ts +164 -0
  64. package/dist/better-auth/access.plugin.js +348 -0
  65. package/dist/better-auth/access.provider.d.ts +80 -0
  66. package/dist/better-auth/access.provider.js +100 -0
  67. package/dist/better-auth/index.d.ts +7 -0
  68. package/dist/better-auth/index.js +4 -0
  69. package/dist/better-auth/organization.bridge.d.ts +66 -0
  70. package/dist/better-auth/organization.bridge.js +144 -0
  71. package/dist/canonical-json.writer.d.ts +12 -0
  72. package/dist/canonical-json.writer.js +30 -0
  73. package/dist/cli/avaccess.bin.d.ts +2 -0
  74. package/dist/cli/avaccess.bin.js +26 -0
  75. package/dist/cli/avaccess.program.d.ts +15 -0
  76. package/dist/cli/avaccess.program.js +166 -0
  77. package/dist/cli/beacon-pins.file.d.ts +14 -0
  78. package/dist/cli/beacon-pins.file.js +62 -0
  79. package/dist/cli/beacon.loader.d.ts +20 -0
  80. package/dist/cli/beacon.loader.js +71 -0
  81. package/dist/cli/cli.context.d.ts +49 -0
  82. package/dist/cli/cli.context.js +66 -0
  83. package/dist/cli/diff.command.d.ts +2 -0
  84. package/dist/cli/diff.command.js +66 -0
  85. package/dist/cli/generate.command.d.ts +2 -0
  86. package/dist/cli/generate.command.js +82 -0
  87. package/dist/cli/keys.command.d.ts +2 -0
  88. package/dist/cli/keys.command.js +96 -0
  89. package/dist/cli/lock.file.d.ts +31 -0
  90. package/dist/cli/lock.file.js +181 -0
  91. package/dist/cli/module.loader.d.ts +13 -0
  92. package/dist/cli/module.loader.js +63 -0
  93. package/dist/cli/policies.diff.d.ts +16 -0
  94. package/dist/cli/policies.diff.js +101 -0
  95. package/dist/cli/pull.command.d.ts +2 -0
  96. package/dist/cli/pull.command.js +234 -0
  97. package/dist/cli/push.command.d.ts +2 -0
  98. package/dist/cli/push.command.js +59 -0
  99. package/dist/cli/registry.client.d.ts +63 -0
  100. package/dist/cli/registry.client.js +287 -0
  101. package/dist/cli/schema.command.d.ts +2 -0
  102. package/dist/cli/schema.command.js +60 -0
  103. package/dist/cli/serve.command.d.ts +6 -0
  104. package/dist/cli/serve.command.js +200 -0
  105. package/dist/cli/status.command.d.ts +2 -0
  106. package/dist/cli/status.command.js +31 -0
  107. package/dist/cli/translator.flag.d.ts +6 -0
  108. package/dist/cli/translator.flag.js +24 -0
  109. package/dist/cli/verify.command.d.ts +2 -0
  110. package/dist/cli/verify.command.js +40 -0
  111. package/dist/client/access-client.factory.d.ts +92 -0
  112. package/dist/client/access-client.factory.js +269 -0
  113. package/dist/client/access-verbs.schema.d.ts +66 -0
  114. package/dist/client/access-verbs.schema.js +159 -0
  115. package/dist/client/verb-rate.limiter.d.ts +116 -0
  116. package/dist/client/verb-rate.limiter.js +358 -0
  117. package/dist/foreign/foreign-facts.d.ts +30 -0
  118. package/dist/foreign/foreign-facts.js +75 -0
  119. package/dist/foreign/foreign.merger.d.ts +10 -0
  120. package/dist/foreign/foreign.merger.js +52 -0
  121. package/dist/foreign-references.check.d.ts +6 -0
  122. package/dist/foreign-references.check.js +131 -0
  123. package/dist/generator/client.emitter.d.ts +28 -0
  124. package/dist/generator/client.emitter.js +411 -0
  125. package/dist/generator/copied-modules.reader.d.ts +14 -0
  126. package/dist/generator/copied-modules.reader.js +80 -0
  127. package/dist/generator/namespace.facts.d.ts +28 -0
  128. package/dist/generator/namespace.facts.js +32 -0
  129. package/dist/generator/orm.translator.d.ts +48 -0
  130. package/dist/generator/orm.translator.js +29 -0
  131. package/dist/generator/prisma7/prisma-schema.reader.d.ts +9 -0
  132. package/dist/generator/prisma7/prisma-schema.reader.js +394 -0
  133. package/dist/generator/prisma7/prisma-where.translator.d.ts +73 -0
  134. package/dist/generator/prisma7/prisma-where.translator.js +138 -0
  135. package/dist/generator/prisma7/prisma7.translator.d.ts +2 -0
  136. package/dist/generator/prisma7/prisma7.translator.js +87 -0
  137. package/dist/generator/schema.emitter.d.ts +14 -0
  138. package/dist/generator/schema.emitter.js +23 -0
  139. package/dist/generator/tsconfig.reader.d.ts +44 -0
  140. package/dist/generator/tsconfig.reader.js +110 -0
  141. package/dist/generator/typescript-literal.writer.d.ts +5 -0
  142. package/dist/generator/typescript-literal.writer.js +42 -0
  143. package/dist/guardrails/guardrails-contract.d.ts +45 -0
  144. package/dist/guardrails/guardrails-contract.js +12 -0
  145. package/dist/guardrails/guardrails.builder.d.ts +48 -0
  146. package/dist/guardrails/guardrails.builder.js +32 -0
  147. package/dist/guardrails/guardrails.compiler.d.ts +10 -0
  148. package/dist/guardrails/guardrails.compiler.js +254 -0
  149. package/dist/guardrails/guardrails.composer.d.ts +7 -0
  150. package/dist/guardrails/guardrails.composer.js +95 -0
  151. package/dist/guardrails/guardrails.hash.d.ts +10 -0
  152. package/dist/guardrails/guardrails.hash.js +38 -0
  153. package/dist/index.d.ts +16 -0
  154. package/dist/index.js +6 -0
  155. package/dist/kiosk/kiosk-verbs.schema.d.ts +19 -0
  156. package/dist/kiosk/kiosk-verbs.schema.js +61 -0
  157. package/dist/kiosk/kiosk.plugin.d.ts +217 -0
  158. package/dist/kiosk/kiosk.plugin.js +877 -0
  159. package/dist/kiosk/kiosk.schema.d.ts +176 -0
  160. package/dist/kiosk/kiosk.schema.js +101 -0
  161. package/dist/kiosk/kiosk.store.d.ts +171 -0
  162. package/dist/kiosk/kiosk.store.js +478 -0
  163. package/dist/kiosk/lan-range.policy.d.ts +31 -0
  164. package/dist/kiosk/lan-range.policy.js +113 -0
  165. package/dist/kiosk/pin.policy.d.ts +9 -0
  166. package/dist/kiosk/pin.policy.js +143 -0
  167. package/dist/kiosk/session-use.marker.d.ts +4 -0
  168. package/dist/kiosk/session-use.marker.js +16 -0
  169. package/dist/lock/lock-contract.d.ts +38 -0
  170. package/dist/lock/lock-contract.js +67 -0
  171. package/dist/lock/lock.verifier.d.ts +27 -0
  172. package/dist/lock/lock.verifier.js +62 -0
  173. package/dist/mcp/agent-scope.gate.d.ts +13 -0
  174. package/dist/mcp/agent-scope.gate.js +75 -0
  175. package/dist/mcp/agent.grant.d.ts +40 -0
  176. package/dist/mcp/agent.grant.js +92 -0
  177. package/dist/mcp/mcp-options.d.ts +60 -0
  178. package/dist/mcp/mcp-options.js +72 -0
  179. package/dist/oauth/access-token.verifier.d.ts +66 -0
  180. package/dist/oauth/access-token.verifier.js +201 -0
  181. package/dist/oauth/oauth-provider.hardening.d.ts +62 -0
  182. package/dist/oauth/oauth-provider.hardening.js +261 -0
  183. package/dist/passwords/argon2id.hasher.d.ts +97 -0
  184. package/dist/passwords/argon2id.hasher.js +256 -0
  185. package/dist/passwords/node-rs-argon2.adapter.d.ts +25 -0
  186. package/dist/passwords/node-rs-argon2.adapter.js +42 -0
  187. package/dist/passwords/passwords.options.d.ts +79 -0
  188. package/dist/passwords/passwords.options.js +212 -0
  189. package/dist/policies-contract.d.ts +219 -0
  190. package/dist/policies-contract.js +8 -0
  191. package/dist/policies.compiler.d.ts +38 -0
  192. package/dist/policies.compiler.js +1433 -0
  193. package/dist/policies.decider.d.ts +103 -0
  194. package/dist/policies.decider.js +390 -0
  195. package/dist/policies.hash.d.ts +10 -0
  196. package/dist/policies.hash.js +54 -0
  197. package/dist/predicate.evaluator.d.ts +62 -0
  198. package/dist/predicate.evaluator.js +378 -0
  199. package/dist/random-secret.generator.d.ts +2 -0
  200. package/dist/random-secret.generator.js +15 -0
  201. package/dist/read-governed-unique.check.d.ts +3 -0
  202. package/dist/read-governed-unique.check.js +21 -0
  203. package/dist/reference-reads.check.d.ts +16 -0
  204. package/dist/reference-reads.check.js +158 -0
  205. package/dist/registry/access.registry.d.ts +173 -0
  206. package/dist/registry/access.registry.js +865 -0
  207. package/dist/registry/beacon.ledger.d.ts +30 -0
  208. package/dist/registry/beacon.ledger.js +93 -0
  209. package/dist/registry/ownership.check.d.ts +54 -0
  210. package/dist/registry/ownership.check.js +221 -0
  211. package/dist/registry/registry.endpoints.d.ts +50 -0
  212. package/dist/registry/registry.endpoints.js +193 -0
  213. package/dist/registry/registry.key.d.ts +7 -0
  214. package/dist/registry/registry.key.js +13 -0
  215. package/dist/registry/registry.options.d.ts +13 -0
  216. package/dist/registry/registry.options.js +28 -0
  217. package/dist/registry/registry.refusal.d.ts +6 -0
  218. package/dist/registry/registry.refusal.js +11 -0
  219. package/dist/registry/registry.schema.d.ts +238 -0
  220. package/dist/registry/registry.schema.js +127 -0
  221. package/dist/resources/auth-tables.catalog.d.ts +96 -0
  222. package/dist/resources/auth-tables.catalog.js +110 -0
  223. package/dist/resources/auth-tables.guard.d.ts +106 -0
  224. package/dist/resources/auth-tables.guard.js +462 -0
  225. package/dist/scope.resolver.d.ts +144 -0
  226. package/dist/scope.resolver.js +529 -0
  227. package/dist/sha256.digest.d.ts +2 -0
  228. package/dist/sha256.digest.js +81 -0
  229. package/dist/standalone/access.server.d.ts +41 -0
  230. package/dist/standalone/access.server.js +301 -0
  231. package/dist/standalone/index.d.ts +1 -0
  232. package/dist/standalone/index.js +1 -0
  233. package/package.json +102 -3
  234. package/skill/SKILL.md +170 -0
  235. package/skill/reference/callers.md +99 -0
  236. package/skill/reference/errors.md +89 -0
  237. package/skill/reference/recipes.md +281 -0
  238. package/skill/reference/rules.md +153 -0
  239. package/skill/reference/setup.md +334 -0
  240. package/src/aventara-where.translator.ts +116 -0
  241. package/src/beacon/beacon.check.ts +204 -0
  242. package/src/canonical-json.writer.ts +51 -0
  243. package/src/generator/prisma7/prisma-where.translator.ts +243 -0
  244. package/src/policies-contract.ts +215 -0
  245. package/src/policies.decider.ts +662 -0
  246. package/src/predicate.evaluator.ts +574 -0
  247. package/src/scope.resolver.ts +819 -0
  248. package/src/sha256.digest.ts +85 -0
@@ -0,0 +1,74 @@
1
+ import type { AccessBuilder } from "../access.builder.js";
2
+ import type { AccessGuardrails, AccessGuardrailsJson } from "../guardrails/guardrails-contract.js";
3
+ import type { AccessLock } from "../lock/lock-contract.js";
4
+ import type { AccessPolicies, AccessPoliciesJson } from "../policies-contract.js";
5
+ import type { AccessClaimsAnswer, AccessClaimsDeclaration, AccessClaimsSource } from "./claims.mapper.js";
6
+ /** The fields each Resource governs, by Resource: what the rules' engine is typed with. */
7
+ type GovernedShape = {
8
+ readonly [resource: string]: readonly string[] | {
9
+ readonly [field: string]: "read" | "write" | "both";
10
+ };
11
+ };
12
+ /** The builder's `govern` block: a mode per governed field. */
13
+ type ModesShape = {
14
+ readonly [resource: string]: {
15
+ readonly [field: string]: "read" | "write" | "both";
16
+ };
17
+ };
18
+ /** The claims a rules principal type `R` reads, by name. */
19
+ type ClaimNamesOf<R> = R extends {
20
+ readonly claims?: infer C;
21
+ } ? keyof NonNullable<C> & string : never;
22
+ /**
23
+ * `policies.claims`, held to the rules: a claim the rules' principal type reads and
24
+ * the declaration lacks is a type error here, naming it.
25
+ */
26
+ type DeclaredFor<R, C extends AccessClaimsDeclaration> = [
27
+ Exclude<ClaimNamesOf<R>, keyof C>
28
+ ] extends [never] ? C : C & {
29
+ readonly [K in Exclude<ClaimNamesOf<R>, keyof C>]: `the rules read the claim "${K}": declare it here, or correct the rules' principal type`;
30
+ };
31
+ /**
32
+ * The rules an instance evaluates: `definePolicies(model)…` as written, or its
33
+ * compiled file (typed, or imported as JSON as `avaccess pull` wrote it).
34
+ */
35
+ export type AccessRules<R, Gov extends GovernedShape> = AccessBuilder<any, R, any, Gov & ModesShape> | AccessPolicies<Gov> | AccessPoliciesJson<Gov>;
36
+ /** The `policies` block. */
37
+ export type AccessPoliciesOptions<C extends AccessClaimsDeclaration, R, Gov extends GovernedShape> = {
38
+ /** The rules this instance evaluates: the builder (its principal type is checked here) or its compiled file. */
39
+ readonly rules: AccessRules<R, Gov>;
40
+ /** The global claims a token carries beside `sub`, by type: `{ role: "string", banned: "boolean" }`. */
41
+ readonly claims: DeclaredFor<R, C>;
42
+ /**
43
+ * A user's claims, when a token is issued: every declared boolean claim, the
44
+ * others where the user has them. Without it, each declared claim is read from
45
+ * the user's field of the same name.
46
+ */
47
+ readonly claimsOf?: (source: AccessClaimsSource) => AccessClaimsAnswer<C> | Promise<AccessClaimsAnswer<C>>;
48
+ /**
49
+ * The org's guardrails, as pulled from the registry (`aventara-access/guardrails@1`):
50
+ * deny-only rules the engine adds on top of `rules`. They only narrow. Every claim
51
+ * they compare must be declared in `claims`.
52
+ */
53
+ readonly guardrails?: AccessGuardrails | AccessGuardrailsJson;
54
+ /**
55
+ * The project's `avAccess.lock.json`, as `avaccess pull` wrote it: the instance
56
+ * refuses to start (`ACCESS_LOCK_MISMATCH`) unless `guardrails`, and `rules` when
57
+ * they are a pulled file, hash to what the lock pins.
58
+ */
59
+ readonly lock?: AccessLock;
60
+ /**
61
+ * `true`: refuse to start without `lock` (`ACCESS_LOCK_MISMATCH`), so a deploy that
62
+ * lost its `avAccess.lock.json` fails at startup instead of running unpinned files;
63
+ * typed rules are then held to the lock's policies hash too. Recommended in
64
+ * production.
65
+ */
66
+ readonly requireLock?: boolean;
67
+ /**
68
+ * How long a token lives, in seconds: from 300 to 900 (5 to 15 minutes), 900 by
69
+ * default. A claim that must take effect soon (`banned`, `suspended`) reaches every
70
+ * service with the user's next token, so this is the longest such a change waits.
71
+ */
72
+ readonly tokenTtl?: number;
73
+ };
74
+ export {};
@@ -0,0 +1,5 @@
1
+ // The `policies` block's types, which `createAccess` and `aventaraAccess()` share: the
2
+ // rules, and the claims they read, held to each other. Both are published from
3
+ // `/auth`; what they are built from stays in this module, so a consumer's
4
+ // declaration emit writes it out rather than naming a module it cannot import.
5
+ export {};
@@ -0,0 +1,35 @@
1
+ /** What an {@link AccessError} refuses. */
2
+ export type AccessErrorCode =
3
+ /** `better-auth` is missing, or outside Access's range (`~1.7.12`), as is an OAuth provider or `cimd()` Access reads. */
4
+ "ACCESS_BETTER_AUTH_VERSION"
5
+ /** A claim the rules read, or one a token carries, that `policies.claims` does not declare. */
6
+ | "ACCESS_CLAIMS_UNDECLARED"
7
+ /** `betterAuth.plugins` holds a plugin `createAccess` installs itself (under any case or spacing of its id), or one that defines `jwt()`'s endpoints or Access's `me` route. */
8
+ | "ACCESS_PLUGIN_DUPLICATE"
9
+ /** An Access block (`policies`, `principal`, `profile`, `registry`, `audit`, `resources`, `passwords`) is not one `createAccess` accepts; `passwords` set beside Better Auth's own `emailAndPassword.password` hook, or argon2id asked of a runtime without `crypto.argon2` or `@node-rs/argon2`; the rules grant what the `resources` block leaves closed; a claim would be read from a field the user can set; Better Auth has no base URL to fix the tokens' issuer; the session cookie is `sameSite: "none"` without trusted origins; Better Auth off its Prisma adapter without `resources.authTables`, or an opened table's secret column not found; or `principal` returned one object for two users. */
10
+ | "ACCESS_OPTIONS_INVALID"
11
+ /** A pushed file names a Resource its namespace does not own, or the org's guardrails file grants. */
12
+ | "ACCESS_OWNERSHIP"
13
+ /** A registry key that is wrong, revoked or rotated out, or one whose kind or namespace does not fit the call. */
14
+ | "ACCESS_KEY_REFUSED"
15
+ /** A pushed file is not a policies file, or the org's guardrails are not a guardrails file, the engine would run from. */
16
+ | "ACCESS_POLICIES_INVALID"
17
+ /** A namespace name that is not one, a namespace the registry does not have (a guardrail's included), or one it has already. */
18
+ | "ACCESS_NAMESPACE"
19
+ /** A stored revision no longer hashes to the hash it was pushed under: it was changed outside the registry. */
20
+ | "ACCESS_REVISION_CHANGED"
21
+ /** A pulled file no longer hashes to the hash `avAccess.lock.json` pins for it, or the engine was handed files the lock does not pin. */
22
+ | "ACCESS_LOCK_MISMATCH"
23
+ /** A Better Auth table `resources` opens is missing: Better Auth has none (its plugin is not installed), or the rules' schema has no Resource for it. */
24
+ | "ACCESS_RESOURCE_MISSING"
25
+ /** A question the engine cannot answer as asked: a `fieldsOf` question without `access: "read"` or `access: "write"`, or with an `action` that does not fit it; or a `hosted` call whose `held` is not a list of Resource names. */
26
+ | "ACCESS_QUESTION_INVALID"
27
+ /** A file reads another namespace's Resources as `foreign` while the two are on different databases: the reader's view of the owner's beacon is not the one the owner pushed, the owner has pushed none, or the push carries none. */
28
+ | "ACCESS_FOREIGN_CROSS_DATABASE"
29
+ /** A beacon that is not what it should be: at startup an owner's row, read through the service's own connection, is missing or does not hash to the lock's pin (or was not checked yet); at push a namespace's own beacon is another namespace's; or a beacon row holds no beacon. */
30
+ | "ACCESS_BEACON_MISMATCH";
31
+ /** A refusal by `createAccess`, the instance it built, its registry, or an engine checking its lock or a question: `code` says which, the message what to change. */
32
+ export declare class AccessError extends Error {
33
+ readonly code: AccessErrorCode;
34
+ constructor(code: AccessErrorCode, message: string);
35
+ }
@@ -0,0 +1,11 @@
1
+ // The one error `createAccess` and the instance it builds throw. Each refusal has a
2
+ // code a program can branch on and a message that says what to change.
3
+ /** A refusal by `createAccess`, the instance it built, its registry, or an engine checking its lock or a question: `code` says which, the message what to change. */
4
+ export class AccessError extends Error {
5
+ code;
6
+ constructor(code, message) {
7
+ super(`Aventara Access: ${message}`);
8
+ this.name = "AccessError";
9
+ this.code = code;
10
+ }
11
+ }
@@ -0,0 +1,275 @@
1
+ import type { Auth, BetterAuthOptions, BetterAuthPlugin } from "better-auth";
2
+ import type { jwt } from "better-auth/plugins/jwt";
3
+ import type { AccessEngine } from "../access.engine.js";
4
+ import type { AccessAuditOptions } from "../audit/audit-event.js";
5
+ import type { AccessBeaconStore } from "../beacon/beacon.store.js";
6
+ import { type AccessKiosk } from "../kiosk/kiosk.plugin.js";
7
+ import { type AccessMcpAuthorization, type AccessMcpOptions } from "../mcp/mcp-options.js";
8
+ import { type AccessPasswordsOptions } from "../passwords/passwords.options.js";
9
+ import { type AccessRegistry } from "../registry/access.registry.js";
10
+ import { type AccessRegistryOptions } from "../registry/registry.options.js";
11
+ import { type AccessResourcesOptions } from "../resources/auth-tables.guard.js";
12
+ import type { AccessPoliciesOptions } from "./access-options.js";
13
+ import { type AccessClaimsDeclaration, type AccessClaimsOf, type AccessIdentity } from "./claims.mapper.js";
14
+ import { type AccessProfileOptions } from "./profile.policy.js";
15
+ export type { AccessPoliciesOptions, AccessRules, } from "./access-options.js";
16
+ type GovernedShape = {
17
+ readonly [resource: string]: readonly string[] | {
18
+ readonly [field: string]: "read" | "write" | "both";
19
+ };
20
+ };
21
+ /** The headers of a request, as the framework hands them to `state`. */
22
+ type RequestHeaders = {
23
+ get(name: string): string | null;
24
+ has(name: string): boolean;
25
+ forEach(callback: (value: string, name: string) => void): void;
26
+ };
27
+ /**
28
+ * The principal (`me`) an instance hands the engine: the rules' principal type when
29
+ * the rules are the builder, else what `principal` returns (by default the identity).
30
+ */
31
+ type AccessPrincipalOf<R, M> = unknown extends R ? M : R;
32
+ /**
33
+ * The request's principal (`me`) from a verified identity: the app maps `sub` to its
34
+ * own profile, and `null` leaves the caller anonymous. With the builder as the rules,
35
+ * it returns their principal type.
36
+ */
37
+ type AccessPrincipalFunction<C extends AccessClaimsDeclaration, R, M> = (identity: AccessIdentity<C>) => (unknown extends R ? M : NoInfer<R>) | null | Promise<(unknown extends R ? M : NoInfer<R>) | null>;
38
+ /**
39
+ * The `principal` option: optional while the identity (`{ sub, claims }`) is itself
40
+ * the rules' principal type, and required when the rules are typed with another.
41
+ */
42
+ type AccessPrincipalOption<C extends AccessClaimsDeclaration, R, M> = [
43
+ AccessIdentity<C>
44
+ ] extends [R] ? {
45
+ /** The request's principal (`me`) from the verified identity; without it, `me` is the identity, `{ sub, claims }`. */
46
+ readonly principal?: AccessPrincipalFunction<C, R, M>;
47
+ } : {
48
+ /** The request's principal (`me`) from the verified identity, typed as the rules' principal. */
49
+ readonly principal: AccessPrincipalFunction<C, R, M>;
50
+ };
51
+ /**
52
+ * The plugins `createAccess` installs itself, by id, as a sentence names each.
53
+ */
54
+ declare const INSTALLED_PLUGINS: {
55
+ readonly "aventara-access": "aventaraAccess()";
56
+ readonly jwt: "jwt()";
57
+ };
58
+ type InstalledPluginId = keyof typeof INSTALLED_PLUGINS;
59
+ /** One `betterAuth.plugins` entry, or the sentence that refuses it. */
60
+ type AccessPluginEntry<E> = E extends {
61
+ readonly id: infer I extends InstalledPluginId;
62
+ } ? `createAccess installs ${(typeof INSTALLED_PLUGINS)[I]} itself: remove it from betterAuth.plugins` : E;
63
+ /** Whether a plugin list holds one `createAccess` installs itself. */
64
+ type HoldsInstalled<L extends readonly unknown[]> = true extends {
65
+ [K in keyof L]: L[K] extends {
66
+ readonly id: InstalledPluginId;
67
+ } ? true : false;
68
+ }[number] ? true : false;
69
+ /**
70
+ * The `betterAuth` block: Better Auth's options as given. A plugin `createAccess`
71
+ * installs itself is a type error at that plugin, which reads as the sentence to fix it.
72
+ */
73
+ type AccessBetterAuthBlock<O extends BetterAuthOptions> = O extends {
74
+ readonly plugins?: infer L extends readonly unknown[];
75
+ } ? HoldsInstalled<L> extends true ? Omit<O, "plugins"> & {
76
+ readonly plugins: {
77
+ [K in keyof L]: AccessPluginEntry<L[K]>;
78
+ };
79
+ } : O : O;
80
+ /** Better Auth's options as `createAccess` builds Better Auth with them: the app's, and `jwt()`. */
81
+ export type AccessBetterAuthOptions<O extends BetterAuthOptions> = Omit<O, "plugins"> & {
82
+ plugins: [
83
+ ...(O extends {
84
+ readonly plugins?: infer L extends readonly unknown[];
85
+ } ? L : []),
86
+ ReturnType<typeof jwt>,
87
+ BetterAuthPlugin & {
88
+ readonly id: "aventara-access";
89
+ }
90
+ ];
91
+ };
92
+ /** `createAccess`'s options. */
93
+ export type AccessOptions<O extends BetterAuthOptions, C extends AccessClaimsDeclaration, R, Gov extends GovernedShape, M, E extends boolean = false, X extends AccessMcpOptions | undefined = AccessMcpOptions | undefined> = {
94
+ /** Better Auth's options, exactly as `betterAuth({...})` takes them. `createAccess` installs `jwt()` itself. */
95
+ readonly betterAuth: AccessBetterAuthBlock<O>;
96
+ /**
97
+ * The shape of app this instance serves: `web` (the default), `service` (bearer
98
+ * tokens only; no caller is handed a new session) or `kiosk` (`web`, plus staff
99
+ * switching by PIN on enrolled devices, each PIN session bound to its device and
100
+ * locked when idle).
101
+ */
102
+ readonly profile?: AccessProfileOptions<C>;
103
+ /**
104
+ * The policy registry: namespaces, their keys, pushed files and the org's
105
+ * guardrails, in tables Better Auth's adapter stores and routes `access.handler`
106
+ * serves under `/access/v1/namespaces`. Off by default: no tables, no routes.
107
+ */
108
+ readonly registry?: AccessRegistryOptions<E>;
109
+ /**
110
+ * The audit log of sign-ins and `can` decisions: `true` writes the `accessAudit`
111
+ * table (Better Auth's `generate`/`migrate` create it), `{ sink }` hands each event
112
+ * to the app instead. Off by default.
113
+ */
114
+ readonly audit?: AccessAuditOptions;
115
+ /**
116
+ * Which of Better Auth's tables are Resources of the rules: `users` (`user`,
117
+ * `session`, `account`) and `members` (the organization plugin's `member`, and its
118
+ * `organization`). Every other table of Better Auth's is closed, and no grant ever
119
+ * opens a secret column. Writes through Aventara skip Better Auth's hooks and
120
+ * caches, so they are limited to a user's `role` and to memberships.
121
+ */
122
+ readonly resources?: AccessResourcesOptions;
123
+ /**
124
+ * How passwords are hashed: argon2id at a named parameter profile,
125
+ * `"owasp-minimum"` (the default) or `"rfc9106-low-memory"`, and with
126
+ * `legacyScrypt: true` Better Auth's scrypt hashes accepted. A hash at another
127
+ * profile, or scrypt, is rehashed at the profile at its account's next sign-in.
128
+ * Without it, and without `betterAuth.emailAndPassword.password`, the
129
+ * default profile is used; an app that sets that hook hashes its own way, and may
130
+ * not set this too.
131
+ */
132
+ readonly passwords?: AccessPasswordsOptions;
133
+ /**
134
+ * Access as the authorization layer of an MCP endpoint (the framework's `mcp`):
135
+ * `{ resource }`, the endpoint's URL. The tokens come from Better Auth's OAuth
136
+ * provider (`@better-auth/oauth-provider`), which goes in
137
+ * `betterAuth.plugins` with the endpoint among its `resources`; `access.mcp` is the
138
+ * framework's `mcp.authorization`. Not on the `service` profile.
139
+ */
140
+ readonly mcp?: X & {
141
+ readonly [K in Exclude<keyof X, keyof AccessMcpOptions>]: never;
142
+ };
143
+ /**
144
+ * The service's own audience, an opt-in (RFC 8707): its URL, as a client names it
145
+ * when it asks Better Auth's OAuth provider for a token for this service
146
+ * (`resource`). With it, a bearer token is taken only when it is the provider's
147
+ * access token addressed to this audience alone; the one-org token `GET /token`
148
+ * issues (its audience the issuer) is refused. Session cookies are read as before.
149
+ * Off by default. The provider goes in `betterAuth.plugins` with the audience among
150
+ * its `resources`. Not on the `service` profile.
151
+ */
152
+ readonly audience?: string;
153
+ } & AccessPoliciesMember<C, R, Gov, E> & AccessPrincipalOption<C, R, M>;
154
+ /**
155
+ * The `policies` block's place in the options: required, except on an instance that
156
+ * serves the registry (`registry: { enabled: true }`), which may have no rules of its
157
+ * own: it then answers every policy question with a deny.
158
+ */
159
+ type AccessPoliciesMember<C extends AccessClaimsDeclaration, R, Gov extends GovernedShape, E extends boolean> = [E] extends [true] ? {
160
+ /** The rules and the claims they read. A registry-only server may leave it out: no claim beside `sub`, and every policy question denied. */
161
+ readonly policies?: AccessPoliciesOptions<C, R, Gov>;
162
+ } : {
163
+ /** The rules and the claims they read. */
164
+ readonly policies: AccessPoliciesOptions<C, R, Gov>;
165
+ };
166
+ export type { AccessRegistryOptions };
167
+ /** `access.registry`: the operator's API when the registry is on, absent when it is off. */
168
+ type AccessRegistryMember<E extends boolean> = [E] extends [true] ? {
169
+ /** The registry's operator API: namespaces, keys and the org's guardrails. */
170
+ readonly registry: AccessRegistry;
171
+ } : [E] extends [false] ? {
172
+ readonly registry?: undefined;
173
+ } : {
174
+ readonly registry?: AccessRegistry | undefined;
175
+ };
176
+ /** What `createAccess` returns: Better Auth's surface, the policy engine and the request state. */
177
+ export type Access<O extends BetterAuthOptions, C extends AccessClaimsDeclaration, Gov extends GovernedShape, M, E extends boolean = false, P extends boolean = false> = {
178
+ /** Better Auth's request handler, with Access's routes: mount it where you would mount Better Auth's. */
179
+ readonly handler: Auth<AccessBetterAuthOptions<O>>["handler"];
180
+ /** Better Auth's server API, as `auth.api`. */
181
+ readonly api: Auth<AccessBetterAuthOptions<O>>["api"];
182
+ /** The options Better Auth is built with: the `betterAuth` block plus the plugins `createAccess` installs. */
183
+ readonly options: AccessBetterAuthOptions<O>;
184
+ /** Types only, as Better Auth's `$Infer`: `typeof access.$Infer.Me` is the principal. */
185
+ readonly $Infer: {
186
+ readonly Session: Auth<AccessBetterAuthOptions<O>>["$Infer"]["Session"];
187
+ readonly Me: M;
188
+ readonly Claims: AccessClaimsOf<C>;
189
+ };
190
+ /** The policy engine, asked about every client and agent request. */
191
+ readonly policy: AccessEngine<Gov>;
192
+ /**
193
+ * The Access server's own beacon row in `_aventara_beacon`, through Better Auth's
194
+ * adapter, on an instance with the registry on whose rules name a namespace: the
195
+ * store `avaccess push --beacon` loads to push it, and `policy.checkBeacons` reads
196
+ * through.
197
+ */
198
+ readonly beacon?: AccessBeaconStore;
199
+ /**
200
+ * The kiosk profile's operator API, for the app's own server (present on that
201
+ * profile only, and no route opens it): `listDevices()` and `revokeDevice(id)`.
202
+ * Another user's PIN is set through Better Auth's server-only endpoint,
203
+ * `access.api.kioskSetUserPin({ body: { userId, pin } })`.
204
+ */
205
+ readonly kiosk?: AccessKiosk;
206
+ /** A request's state: `me`, from its bearer token or (profiles `web` and `kiosk`) its session cookie, else `null`. */
207
+ state(input: {
208
+ readonly headers: RequestHeaders;
209
+ readonly request?: unknown;
210
+ }): Promise<{
211
+ readonly me: M | null;
212
+ }>;
213
+ /**
214
+ * What the framework's `$access` needs: where Access is mounted (`url`, from
215
+ * Better Auth's `baseURL` and `basePath`), and each verb this instance serves,
216
+ * with its route under `url`, the JSON Schema of its arguments and of its result
217
+ * (`me`'s: the token identity, `{ sub, claims }`, with the declared claims), and
218
+ * its server call. `call` runs the verb in-process through Better Auth's API with
219
+ * the request's headers, held to the same checks as the route (origin, profile,
220
+ * audit), so a cookie plugin such as `nextCookies()` sets the browser's cookie
221
+ * from a Server Action. A verb the instance does not serve is absent: `signIn`,
222
+ * `signUp` and `resetPassword` need `emailAndPassword`, the `service` profile
223
+ * has no `signIn` or `signUp`, and only the `kiosk` profile has its verbs:
224
+ * `switchUser` (`{ userId, pin }`) and `lock` on an enrolled device, `setPin`
225
+ * (`{ pin }`) from a fresh session opened with full credentials, and
226
+ * `enrollDevice` (`{ name }`) and `revokeDevice` (`{ deviceId }`) from one
227
+ * `canEnrollDevice` allows.
228
+ */
229
+ readonly client: {
230
+ /** Where the app mounted Access: absolute, or root-relative (`"/api/auth"`) when Better Auth's base URL follows the request. */
231
+ readonly url: string;
232
+ readonly verbs: {
233
+ readonly [V in "signIn" | "signUp" | "signOut" | "resetPassword" | "me" | "switchUser" | "lock" | "setPin" | "enrollDevice" | "revokeDevice"]?: {
234
+ readonly method: "GET" | "POST";
235
+ /** Under `url`: `"/sign-in/email"`. */
236
+ readonly path: string;
237
+ /** The JSON Schema of the arguments; absent when the verb takes none. */
238
+ readonly args?: {
239
+ readonly [key: string]: unknown;
240
+ };
241
+ /** The JSON Schema of the result (`me`: of the non-null value). */
242
+ readonly result: {
243
+ readonly [key: string]: unknown;
244
+ };
245
+ /** The verb, run in-process with the request's headers: its result, cut to `result`. */
246
+ call(input: {
247
+ readonly args: unknown;
248
+ readonly headers: RequestHeaders;
249
+ readonly request?: unknown;
250
+ }): Promise<unknown>;
251
+ };
252
+ };
253
+ };
254
+ } & AccessRegistryMember<E> & AccessMcpMember<C, P>;
255
+ /** Whether an `mcp` block is given: `true`, `false`, or `boolean` when the types cannot tell. */
256
+ type McpGiven<X> = [X] extends [undefined] ? false : [X] extends [AccessMcpOptions] ? true : boolean;
257
+ /** `access.mcp`: the framework's `mcp.authorization` when `mcp` is given, absent when it is not. */
258
+ type AccessMcpMember<C extends AccessClaimsDeclaration, P extends boolean> = [
259
+ P
260
+ ] extends [true] ? {
261
+ /** The framework's `mcp.authorization`: `mcp: { path: "/mcp", authorization: access.mcp }`. */
262
+ readonly mcp: AccessMcpAuthorization<AccessClaimsOf<C>>;
263
+ } : [P] extends [false] ? {
264
+ readonly mcp?: undefined;
265
+ } : {
266
+ readonly mcp?: AccessMcpAuthorization<AccessClaimsOf<C>> | undefined;
267
+ };
268
+ /**
269
+ * Builds an Access instance: Better Auth (from the `betterAuth` block, with `jwt()`
270
+ * and the Access plugin installed), the policy engine (from `policies.rules`) and
271
+ * the request state the framework's `access` option reads. It mounts nothing and
272
+ * opens no connection; `better-auth` is loaded here, and must be the exact version
273
+ * Access is built against.
274
+ */
275
+ export declare function createAccess<O extends BetterAuthOptions, const C extends AccessClaimsDeclaration, R = unknown, Gov extends GovernedShape = Record<never, never>, M = AccessIdentity<C>, const E extends boolean = false, X extends AccessMcpOptions | undefined = undefined>(options: AccessOptions<O, C, R, Gov, M, E, X>): Access<O, C, Gov, AccessPrincipalOf<R, M>, E, McpGiven<X>>;