@toa.io/extensions.exposition 1.0.0-alpha.282 → 1.0.0-alpha.283

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 (312) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/components/exposition.octets/manifest.toa.yaml +11 -0
  3. package/components/exposition.octets/types/index.d.ts +3 -0
  4. package/components/exposition.octets/types/toa.d.ts +41 -0
  5. package/components/identity.bans/types/index.d.ts +3 -0
  6. package/components/identity.bans/types/toa.d.ts +34 -0
  7. package/components/identity.basic/manifest.toa.yaml +13 -2
  8. package/components/identity.basic/operations/add.d.ts +3 -3
  9. package/components/identity.basic/operations/authenticate.d.ts +2 -2
  10. package/components/identity.basic/operations/check.d.ts +1 -1
  11. package/components/identity.basic/operations/delete.d.ts +2 -2
  12. package/components/identity.basic/operations/incept.d.ts +2 -2
  13. package/components/identity.basic/operations/info.d.ts +1 -1
  14. package/components/identity.basic/operations/transit.d.ts +4 -3
  15. package/components/identity.basic/operations/transit.js +2 -1
  16. package/components/identity.basic/operations/transit.js.map +1 -1
  17. package/components/identity.basic/source/add.ts +3 -3
  18. package/components/identity.basic/source/authenticate.ts +2 -2
  19. package/components/identity.basic/source/check.ts +1 -1
  20. package/components/identity.basic/source/delete.ts +2 -2
  21. package/components/identity.basic/source/incept.ts +2 -2
  22. package/components/identity.basic/source/info.ts +1 -1
  23. package/components/identity.basic/source/transit.ts +6 -4
  24. package/components/identity.basic/tsconfig.tsbuildinfo +1 -1
  25. package/components/identity.basic/types/index.d.ts +21 -0
  26. package/components/identity.basic/types/toa.d.ts +121 -0
  27. package/components/identity.clients/manifest.toa.yaml +243 -0
  28. package/components/identity.clients/operations/describe.d.ts +27 -0
  29. package/components/identity.clients/operations/describe.js +44 -0
  30. package/components/identity.clients/operations/describe.js.map +1 -0
  31. package/components/identity.clients/operations/lib/Context.d.ts +29 -0
  32. package/components/identity.clients/operations/lib/Context.js +2 -0
  33. package/components/identity.clients/operations/lib/Context.js.map +1 -0
  34. package/components/identity.clients/operations/lib/Entity.d.ts +29 -0
  35. package/components/identity.clients/operations/lib/Entity.js +2 -0
  36. package/components/identity.clients/operations/lib/Entity.js.map +1 -0
  37. package/components/identity.clients/operations/lib/canonical.d.ts +11 -0
  38. package/components/identity.clients/operations/lib/canonical.js +24 -0
  39. package/components/identity.clients/operations/lib/canonical.js.map +1 -0
  40. package/components/identity.clients/operations/lib/cimd.d.ts +8 -0
  41. package/components/identity.clients/operations/lib/cimd.js +86 -0
  42. package/components/identity.clients/operations/lib/cimd.js.map +1 -0
  43. package/components/identity.clients/operations/lib/errors.d.ts +7 -0
  44. package/components/identity.clients/operations/lib/errors.js +5 -0
  45. package/components/identity.clients/operations/lib/errors.js.map +1 -0
  46. package/components/identity.clients/operations/lib/index.d.ts +6 -0
  47. package/components/identity.clients/operations/lib/index.js +7 -0
  48. package/components/identity.clients/operations/lib/index.js.map +1 -0
  49. package/components/identity.clients/operations/lib/redirect.d.ts +10 -0
  50. package/components/identity.clients/operations/lib/redirect.js +32 -0
  51. package/components/identity.clients/operations/lib/redirect.js.map +1 -0
  52. package/components/identity.clients/operations/register.d.ts +37 -0
  53. package/components/identity.clients/operations/register.js +84 -0
  54. package/components/identity.clients/operations/register.js.map +1 -0
  55. package/components/identity.clients/source/describe.ts +65 -0
  56. package/components/identity.clients/source/lib/Context.ts +38 -0
  57. package/components/identity.clients/source/lib/Entity.ts +31 -0
  58. package/components/identity.clients/source/lib/canonical.test.ts +43 -0
  59. package/components/identity.clients/source/lib/canonical.ts +27 -0
  60. package/components/identity.clients/source/lib/cimd.test.ts +120 -0
  61. package/components/identity.clients/source/lib/cimd.ts +107 -0
  62. package/components/identity.clients/source/lib/errors.ts +4 -0
  63. package/components/identity.clients/source/lib/index.ts +6 -0
  64. package/components/identity.clients/source/lib/redirect.test.ts +41 -0
  65. package/components/identity.clients/source/lib/redirect.ts +35 -0
  66. package/components/identity.clients/source/register.ts +125 -0
  67. package/components/identity.clients/tsconfig.json +10 -0
  68. package/components/identity.clients/tsconfig.tsbuildinfo +1 -0
  69. package/components/identity.clients/types/index.d.ts +3 -0
  70. package/components/identity.clients/types/toa.d.ts +109 -0
  71. package/components/identity.credentials/operations/list.d.ts +2 -1
  72. package/components/identity.credentials/operations/list.js.map +1 -1
  73. package/components/identity.credentials/source/list.ts +2 -1
  74. package/components/identity.credentials/tsconfig.tsbuildinfo +1 -1
  75. package/components/identity.credentials/types/index.d.ts +3 -0
  76. package/components/identity.credentials/types/toa.d.ts +30 -0
  77. package/components/identity.federation/manifest.toa.yaml +37 -1
  78. package/components/identity.federation/operations/authenticate.d.ts +1 -1
  79. package/components/identity.federation/operations/lib/Ctx.d.ts +2 -2
  80. package/components/identity.federation/operations/lib/decode.js +22 -8
  81. package/components/identity.federation/operations/lib/decode.js.map +1 -1
  82. package/components/identity.federation/operations/lib/errors.d.ts +7 -0
  83. package/components/identity.federation/operations/lib/errors.js +4 -0
  84. package/components/identity.federation/operations/lib/errors.js.map +1 -1
  85. package/components/identity.federation/operations/lib/exchange.js +11 -6
  86. package/components/identity.federation/operations/lib/exchange.js.map +1 -1
  87. package/components/identity.federation/operations/types/configuration.d.ts +1 -1
  88. package/components/identity.federation/operations/types/context.d.ts +3 -2
  89. package/components/identity.federation/source/authenticate.ts +1 -1
  90. package/components/identity.federation/source/lib/Ctx.ts +2 -2
  91. package/components/identity.federation/source/lib/decode.ts +25 -9
  92. package/components/identity.federation/source/lib/errors.ts +5 -0
  93. package/components/identity.federation/source/lib/exchange.ts +11 -7
  94. package/components/identity.federation/source/types/configuration.ts +1 -1
  95. package/components/identity.federation/source/types/context.ts +3 -2
  96. package/components/identity.federation/tsconfig.tsbuildinfo +1 -1
  97. package/components/identity.federation/types/index.d.ts +3 -0
  98. package/components/identity.federation/types/toa.d.ts +127 -0
  99. package/components/identity.grants/manifest.toa.yaml +245 -0
  100. package/components/identity.grants/operations/authorize.d.ts +35 -0
  101. package/components/identity.grants/operations/authorize.js +54 -0
  102. package/components/identity.grants/operations/authorize.js.map +1 -0
  103. package/components/identity.grants/operations/exchange.d.ts +37 -0
  104. package/components/identity.grants/operations/exchange.js +89 -0
  105. package/components/identity.grants/operations/exchange.js.map +1 -0
  106. package/components/identity.grants/operations/lib/code.d.ts +15 -0
  107. package/components/identity.grants/operations/lib/code.js +30 -0
  108. package/components/identity.grants/operations/lib/code.js.map +1 -0
  109. package/components/identity.grants/operations/lib/identify.d.ts +6 -0
  110. package/components/identity.grants/operations/lib/identify.js +15 -0
  111. package/components/identity.grants/operations/lib/identify.js.map +1 -0
  112. package/components/identity.grants/operations/lib/index.d.ts +3 -0
  113. package/components/identity.grants/operations/lib/index.js +3 -0
  114. package/components/identity.grants/operations/lib/index.js.map +1 -0
  115. package/components/identity.grants/operations/list.d.ts +13 -0
  116. package/components/identity.grants/operations/list.js +18 -0
  117. package/components/identity.grants/operations/list.js.map +1 -0
  118. package/components/identity.grants/operations/revoke.d.ts +18 -0
  119. package/components/identity.grants/operations/revoke.js +25 -0
  120. package/components/identity.grants/operations/revoke.js.map +1 -0
  121. package/components/identity.grants/source/authorize.ts +90 -0
  122. package/components/identity.grants/source/exchange.ts +130 -0
  123. package/components/identity.grants/source/lib/code.ts +39 -0
  124. package/components/identity.grants/source/lib/identify.ts +16 -0
  125. package/components/identity.grants/source/lib/index.ts +3 -0
  126. package/components/identity.grants/source/list.ts +28 -0
  127. package/components/identity.grants/source/revoke.ts +38 -0
  128. package/components/identity.grants/tsconfig.json +10 -0
  129. package/components/identity.grants/tsconfig.tsbuildinfo +1 -0
  130. package/components/identity.grants/types/index.d.ts +60 -0
  131. package/components/identity.grants/types/toa.d.ts +108 -0
  132. package/components/identity.keys/manifest.toa.yaml +1 -0
  133. package/components/identity.keys/operations/create.d.ts +1 -1
  134. package/components/identity.keys/operations/revoke.d.ts +1 -1
  135. package/components/identity.keys/source/create.ts +1 -1
  136. package/components/identity.keys/source/revoke.ts +1 -1
  137. package/components/identity.keys/tsconfig.tsbuildinfo +1 -1
  138. package/components/identity.keys/types/index.d.ts +3 -0
  139. package/components/identity.keys/types/toa.d.ts +47 -0
  140. package/components/identity.otp/operations/lib/Context.d.ts +4 -2
  141. package/components/identity.otp/source/lib/Context.ts +4 -2
  142. package/components/identity.otp/tsconfig.tsbuildinfo +1 -1
  143. package/components/identity.otp/types/index.d.ts +3 -0
  144. package/components/identity.otp/types/toa.d.ts +56 -0
  145. package/components/identity.passkeys/manifest.toa.yaml +3 -0
  146. package/components/identity.passkeys/operations/authenticate.d.ts +1 -1
  147. package/components/identity.passkeys/operations/challenge.d.ts +1 -1
  148. package/components/identity.passkeys/operations/create.d.ts +1 -1
  149. package/components/identity.passkeys/operations/types/Context.d.ts +2 -1
  150. package/components/identity.passkeys/operations/use.d.ts +1 -1
  151. package/components/identity.passkeys/source/authenticate.ts +1 -1
  152. package/components/identity.passkeys/source/challenge.ts +1 -1
  153. package/components/identity.passkeys/source/create.ts +1 -1
  154. package/components/identity.passkeys/source/types/Context.ts +2 -1
  155. package/components/identity.passkeys/source/use.ts +1 -1
  156. package/components/identity.passkeys/tsconfig.tsbuildinfo +1 -1
  157. package/components/identity.passkeys/types/index.d.ts +3 -0
  158. package/components/identity.passkeys/types/toa.d.ts +120 -0
  159. package/components/identity.roles/operations/principal.d.ts +1 -1
  160. package/components/identity.roles/source/principal.ts +1 -1
  161. package/components/identity.roles/tsconfig.tsbuildinfo +1 -1
  162. package/components/identity.roles/types/index.d.ts +3 -0
  163. package/components/identity.roles/types/toa.d.ts +43 -0
  164. package/components/identity.tokens/manifest.toa.yaml +34 -3
  165. package/components/identity.tokens/operations/authenticate.d.ts +2 -1
  166. package/components/identity.tokens/operations/authenticate.js +8 -0
  167. package/components/identity.tokens/operations/authenticate.js.map +1 -1
  168. package/components/identity.tokens/operations/decrypt.d.ts +2 -1
  169. package/components/identity.tokens/operations/decrypt.js +2 -2
  170. package/components/identity.tokens/operations/decrypt.js.map +1 -1
  171. package/components/identity.tokens/operations/encrypt.d.ts +2 -1
  172. package/components/identity.tokens/operations/encrypt.js.map +1 -1
  173. package/components/identity.tokens/operations/issue.d.ts +2 -1
  174. package/components/identity.tokens/operations/issue.js +2 -1
  175. package/components/identity.tokens/operations/issue.js.map +1 -1
  176. package/components/identity.tokens/operations/lib/form.d.ts +8 -0
  177. package/components/identity.tokens/operations/lib/form.js +24 -0
  178. package/components/identity.tokens/operations/lib/form.js.map +1 -0
  179. package/components/identity.tokens/operations/lib/index.d.ts +2 -1
  180. package/components/identity.tokens/operations/lib/index.js +1 -1
  181. package/components/identity.tokens/operations/lib/index.js.map +1 -1
  182. package/components/identity.tokens/source/authenticate.test.ts +8 -5
  183. package/components/identity.tokens/source/authenticate.ts +12 -1
  184. package/components/identity.tokens/source/decrypt.test.ts +1 -1
  185. package/components/identity.tokens/source/decrypt.ts +4 -3
  186. package/components/identity.tokens/source/encrypt.test.ts +1 -1
  187. package/components/identity.tokens/source/encrypt.ts +2 -1
  188. package/components/identity.tokens/source/issue.test.ts +71 -0
  189. package/components/identity.tokens/source/issue.ts +4 -2
  190. package/components/identity.tokens/source/lib/form.test.ts +25 -0
  191. package/components/identity.tokens/source/lib/form.ts +31 -0
  192. package/components/identity.tokens/source/lib/index.ts +2 -1
  193. package/components/identity.tokens/tsconfig.tsbuildinfo +1 -1
  194. package/components/identity.tokens/types/index.d.ts +61 -0
  195. package/components/identity.tokens/types/toa.d.ts +113 -0
  196. package/documentation/cache.md +10 -1
  197. package/documentation/consent.md +101 -0
  198. package/documentation/identity.md +3 -1
  199. package/documentation/io.md +36 -2
  200. package/documentation/oauth.md +179 -0
  201. package/documentation/protocol.md +4 -0
  202. package/features/auth.bearer.feature +120 -0
  203. package/features/cache.feature +46 -0
  204. package/features/oauth.clients.feature +195 -0
  205. package/features/oauth.discovery.feature +165 -0
  206. package/features/oauth.grants.feature +286 -0
  207. package/features/steps/Gateway.ts +6 -1
  208. package/features/steps/Parameters.ts +4 -0
  209. package/features/steps/components/echo/manifest.toa.yaml +2 -0
  210. package/features/steps/components/octets.tester/manifest.toa.yaml +2 -0
  211. package/features/steps/components/octets.tester/operations/redirect.js +6 -1
  212. package/features/steps/components/users/manifest.toa.yaml +1 -0
  213. package/package.json +8 -6
  214. package/readme.md +3 -0
  215. package/schemas/annotation.cos.yaml +30 -0
  216. package/source/Annotation.ts +23 -0
  217. package/source/Factory.ts +1 -1
  218. package/source/HTTP/Server.ts +9 -5
  219. package/source/HTTP/formats/form.ts +21 -0
  220. package/source/HTTP/formats/index.ts +17 -2
  221. package/source/HTTP/messages.test.ts +25 -1
  222. package/source/HTTP/messages.ts +10 -3
  223. package/source/Interception.ts +8 -2
  224. package/source/deployment.ts +4 -1
  225. package/source/directives/auth/Authorization.ts +46 -19
  226. package/source/directives/auth/Incept.ts +14 -9
  227. package/source/directives/auth/schemes.test.ts +8 -4
  228. package/source/directives/auth/schemes.ts +22 -9
  229. package/source/directives/auth/types.ts +5 -2
  230. package/source/directives/cache/Cache.ts +13 -4
  231. package/source/directives/cache/Control.ts +0 -3
  232. package/source/directives/flow/Fetch.ts +1 -1
  233. package/source/directives/index.ts +2 -1
  234. package/source/directives/io/IO.ts +2 -0
  235. package/source/directives/io/Output.ts +4 -1
  236. package/source/directives/io/Status.test.ts +84 -0
  237. package/source/directives/io/Status.ts +46 -0
  238. package/source/directives/oauth/Discovery.ts +76 -0
  239. package/source/directives/oauth/documents.ts +113 -0
  240. package/source/directives/oauth/index.ts +3 -0
  241. package/source/directives/octets/Delete.ts +1 -1
  242. package/source/directives/octets/Get.ts +1 -1
  243. package/source/directives/octets/Workflow.ts +1 -1
  244. package/source/directives/octets/workflows/Execution.ts +1 -1
  245. package/source/index.ts +6 -0
  246. package/source/octets.d.ts +17 -0
  247. package/source/userland.ts +47 -0
  248. package/transpiled/Annotation.d.ts +17 -0
  249. package/transpiled/Factory.js +1 -1
  250. package/transpiled/Factory.js.map +1 -1
  251. package/transpiled/HTTP/Server.d.ts +4 -1
  252. package/transpiled/HTTP/Server.js +4 -3
  253. package/transpiled/HTTP/Server.js.map +1 -1
  254. package/transpiled/HTTP/formats/form.d.ts +9 -0
  255. package/transpiled/HTTP/formats/form.js +18 -0
  256. package/transpiled/HTTP/formats/form.js.map +1 -0
  257. package/transpiled/HTTP/formats/index.d.ts +10 -2
  258. package/transpiled/HTTP/formats/index.js +10 -0
  259. package/transpiled/HTTP/formats/index.js.map +1 -1
  260. package/transpiled/HTTP/messages.d.ts +6 -0
  261. package/transpiled/HTTP/messages.js +3 -3
  262. package/transpiled/HTTP/messages.js.map +1 -1
  263. package/transpiled/Interception.d.ts +4 -1
  264. package/transpiled/Interception.js +4 -2
  265. package/transpiled/Interception.js.map +1 -1
  266. package/transpiled/deployment.js +2 -0
  267. package/transpiled/deployment.js.map +1 -1
  268. package/transpiled/directives/auth/Authorization.d.ts +1 -1
  269. package/transpiled/directives/auth/Authorization.js +38 -18
  270. package/transpiled/directives/auth/Authorization.js.map +1 -1
  271. package/transpiled/directives/auth/Incept.d.ts +1 -1
  272. package/transpiled/directives/auth/Incept.js +11 -7
  273. package/transpiled/directives/auth/Incept.js.map +1 -1
  274. package/transpiled/directives/auth/schemes.d.ts +16 -4
  275. package/transpiled/directives/auth/schemes.js +20 -8
  276. package/transpiled/directives/auth/schemes.js.map +1 -1
  277. package/transpiled/directives/auth/types.d.ts +4 -2
  278. package/transpiled/directives/cache/Cache.js +9 -2
  279. package/transpiled/directives/cache/Cache.js.map +1 -1
  280. package/transpiled/directives/cache/Control.js +0 -2
  281. package/transpiled/directives/cache/Control.js.map +1 -1
  282. package/transpiled/directives/index.js +2 -1
  283. package/transpiled/directives/index.js.map +1 -1
  284. package/transpiled/directives/io/IO.js +2 -0
  285. package/transpiled/directives/io/IO.js.map +1 -1
  286. package/transpiled/directives/io/Output.js +4 -1
  287. package/transpiled/directives/io/Output.js.map +1 -1
  288. package/transpiled/directives/io/Status.d.ts +19 -0
  289. package/transpiled/directives/io/Status.js +34 -0
  290. package/transpiled/directives/io/Status.js.map +1 -0
  291. package/transpiled/directives/oauth/Discovery.d.ts +23 -0
  292. package/transpiled/directives/oauth/Discovery.js +58 -0
  293. package/transpiled/directives/oauth/Discovery.js.map +1 -0
  294. package/transpiled/directives/oauth/documents.d.ts +9 -0
  295. package/transpiled/directives/oauth/documents.js +82 -0
  296. package/transpiled/directives/oauth/documents.js.map +1 -0
  297. package/transpiled/directives/oauth/index.d.ts +2 -0
  298. package/transpiled/directives/oauth/index.js +3 -0
  299. package/transpiled/directives/oauth/index.js.map +1 -0
  300. package/transpiled/index.d.ts +2 -0
  301. package/transpiled/userland.d.ts +39 -0
  302. package/transpiled/userland.js +7 -0
  303. package/transpiled/userland.js.map +1 -0
  304. package/tsconfig.tsbuildinfo +1 -1
  305. package/components/identity.basic/operations/types.d.ts +0 -61
  306. package/components/identity.basic/operations/types.js +0 -2
  307. package/components/identity.basic/operations/types.js.map +0 -1
  308. package/components/identity.basic/source/types.ts +0 -69
  309. package/components/identity.tokens/operations/lib/types.d.ts +0 -88
  310. package/components/identity.tokens/operations/lib/types.js +0 -2
  311. package/components/identity.tokens/operations/lib/types.js.map +0 -1
  312. package/components/identity.tokens/source/lib/types.ts +0 -102
@@ -0,0 +1,127 @@
1
+ // Written by `toa types`. Every run rewrites it.
2
+ // What a manifest does not state belongs in a file of your own.
3
+
4
+ import type { Query, RemoteError } from '@toa.io/core'
5
+ import type { Secret } from '@toa.io/extensions.configuration'
6
+ import type { FetchInit } from '@toa.io/extensions.fetch'
7
+ import type { Logs, Span } from '@toa.io/extensions.telemetry'
8
+ import type { Readable } from 'node:stream'
9
+
10
+ export interface Entity {
11
+ /** The authority token is valid for */
12
+ authority: string
13
+ /** The issuer, or signer, of the token, URI like `https://accounts.google.com` */
14
+ iss: string
15
+ /** The ID that represents the principal making the request */
16
+ sub: string
17
+ /** Identity associated with these credentials */
18
+ identity: string
19
+ id: string
20
+ _version?: number
21
+ _created?: number
22
+ _updated?: number
23
+ _deleted?: number | null
24
+ }
25
+
26
+ export type TransitInput = {
27
+ authority: string
28
+ iss: string
29
+ sub: string
30
+ identity: string
31
+ }
32
+
33
+ export type CreateInput = {
34
+ scheme: "bearer" | "code"
35
+ authority: string
36
+ credentials: string
37
+ id: string
38
+ }
39
+
40
+ export type InceptInput = {
41
+ scheme: "bearer" | "code"
42
+ authority: string
43
+ credentials: string
44
+ id: string
45
+ }
46
+
47
+ export type InceptOutput = {
48
+ id?: string
49
+ }
50
+
51
+ export type AuthenticateInput = {
52
+ scheme: "bearer" | "code"
53
+ authority: string
54
+ credentials: string
55
+ }
56
+
57
+ export type AuthenticateOutput = {
58
+ identity?: {
59
+ id: string
60
+ claims: {
61
+ iss: string
62
+ aud?: string
63
+ sub: string
64
+ [key: string]: unknown
65
+ }
66
+ }
67
+ }
68
+
69
+ export type DecodeInput = string
70
+
71
+ export type DecodeOutput = {
72
+ iss: string
73
+ aud?: string
74
+ sub: string
75
+ [key: string]: unknown
76
+ }
77
+
78
+ export type ListInput = {
79
+ authority: string
80
+ identity: string
81
+ }
82
+
83
+ export type DeleteInput = {
84
+ authority: string
85
+ identity: string
86
+ credential: string
87
+ }
88
+
89
+ export interface Component {
90
+ transit: (request: { input: TransitInput, query?: Query<Entity>, task?: boolean }) => Promise<Entity>
91
+ create: (request: { input: CreateInput, task?: boolean }) => Promise<unknown | RemoteError<"EXISTS" | "TOKEN" | "TRUST" | "RESPONSE" | "CONFIG" | "NO_TOKEN" | "ISS" | "SUB" | "EXP" | "REPLAY" | "CODE_NOT_ENABLED" | "CODE_SCHEMA">>
92
+ incept: (request: { input: InceptInput, task?: boolean }) => Promise<InceptOutput | RemoteError<"EXISTS" | "TOKEN" | "TRUST" | "RESPONSE" | "CONFIG" | "NO_TOKEN" | "ISS" | "SUB" | "EXP" | "REPLAY" | "CODE_NOT_ENABLED" | "CODE_SCHEMA">>
93
+ authenticate: (request: { input: AuthenticateInput, task?: boolean }) => Promise<AuthenticateOutput | RemoteError<"NOT_FOUND" | "TOKEN" | "TRUST" | "RESPONSE" | "CONFIG" | "NO_TOKEN" | "ISS" | "SUB" | "EXP" | "REPLAY" | "CODE_NOT_ENABLED" | "CODE_SCHEMA">>
94
+ decode: (request: { input: DecodeInput, task?: boolean }) => Promise<DecodeOutput>
95
+ list: (request: { input: ListInput, task?: boolean }) => Promise<unknown>
96
+ delete: (request: { input: DeleteInput, task?: boolean }) => Promise<unknown>
97
+ assign: (request: { input?: null, query?: Query<Entity>, task?: boolean }) => Promise<Entity>
98
+ ensure: (request: { input?: null, query?: Query<Entity>, task?: boolean }) => Promise<Entity>
99
+ enumerate: (request: { input?: null, query?: Query<Entity>, task?: boolean }) => Promise<Entity[]>
100
+ observe: (request: { input?: null, query?: Query<Entity>, task?: boolean }) => Promise<Entity | null>
101
+ stream: (request: { input?: null, query?: Query<Entity>, task?: boolean }) => Promise<Readable>
102
+ terminate: (request: { input?: null, query?: Query<Entity>, task?: boolean }) => Promise<Entity>
103
+ }
104
+
105
+ export interface Configuration {
106
+ trust?: Array<{
107
+ /** Allowed values for a token `iss` field */
108
+ iss: string
109
+ /** Acceptable `aud` value(s) */
110
+ aud: string | string[]
111
+ signature?: {
112
+ iss: string
113
+ kid: string
114
+ /** PKCS8 private key in PEM form */
115
+ key: string
116
+ }
117
+ /** Client secret for the Identity Provider. Required for Authorization Code Flow. */
118
+ secret?: string
119
+ }>
120
+ /** Subject that will be assigned the `system` Role */
121
+ principal?: {
122
+ authority: string
123
+ iss: string
124
+ sub: string
125
+ }
126
+ assert?: boolean
127
+ }
@@ -0,0 +1,245 @@
1
+ namespace: identity
2
+ name: grants
3
+
4
+ # What a user allowed a client to do on their behalf. The authorization code is not here:
5
+ # it is single-use and lives seconds, so it is held in the stash and redeemed atomically.
6
+ entity:
7
+ associated: true
8
+ schema:
9
+ type: object
10
+ properties:
11
+ authority:
12
+ type: string
13
+ identity:
14
+ type: string
15
+ client:
16
+ type: string
17
+ scope:
18
+ type: array
19
+ items:
20
+ type: string
21
+ resource:
22
+ type: array
23
+ items:
24
+ type: string
25
+ kid:
26
+ description: The identity.keys record backing the access token, revoked with the grant
27
+ type: string
28
+ revokedAt:
29
+ type: integer
30
+ required:
31
+ - authority
32
+ - identity
33
+ - client
34
+ index:
35
+ identity:
36
+ authority: asc
37
+ identity: asc
38
+
39
+ operations:
40
+ transit:
41
+ concurrency: retry
42
+ input:
43
+ type: object
44
+ properties:
45
+ authority:
46
+ type: string
47
+ identity:
48
+ type: string
49
+ client:
50
+ type: string
51
+ scope:
52
+ type: array
53
+ items:
54
+ type: string
55
+ resource:
56
+ type: array
57
+ items:
58
+ type: string
59
+ kid:
60
+ type: string
61
+ required:
62
+ - authority
63
+ - identity
64
+ - client
65
+
66
+ authorize:
67
+ query: false
68
+ input:
69
+ type: object
70
+ properties:
71
+ authority:
72
+ type: string
73
+ identity:
74
+ type: string
75
+ client:
76
+ type: string
77
+ maxLength: 2048
78
+ redirect:
79
+ type: string
80
+ maxLength: 2048
81
+ challenge:
82
+ description: PKCE code challenge, S256 of the verifier
83
+ type: string
84
+ minLength: 43
85
+ maxLength: 128
86
+ method:
87
+ type: string
88
+ scope:
89
+ type: array
90
+ items:
91
+ type: string
92
+ resource:
93
+ type: array
94
+ items:
95
+ type: string
96
+ maxLength: 2048
97
+ required:
98
+ - authority
99
+ - identity
100
+ - client
101
+ - redirect
102
+ - challenge
103
+ - method
104
+ output:
105
+ type: object
106
+ properties:
107
+ status:
108
+ description: Read and removed by `io:status`
109
+ type: number
110
+ code:
111
+ type: string
112
+ expires_in:
113
+ type: number
114
+ error:
115
+ type: string
116
+ error_description:
117
+ type: string
118
+
119
+ exchange:
120
+ query: false
121
+ input:
122
+ type: object
123
+ properties:
124
+ authority:
125
+ type: string
126
+ grant_type:
127
+ type: string
128
+ code:
129
+ type: string
130
+ maxLength: 512
131
+ code_verifier:
132
+ type: string
133
+ minLength: 43
134
+ maxLength: 128
135
+ redirect_uri:
136
+ type: string
137
+ maxLength: 2048
138
+ client_id:
139
+ type: string
140
+ maxLength: 2048
141
+ resource:
142
+ description: A form repeats a name to say a list, so either shape arrives
143
+ type: [string, array]
144
+ required:
145
+ - authority
146
+ - grant_type
147
+ output:
148
+ type: object
149
+ properties:
150
+ status:
151
+ type: number
152
+ access_token:
153
+ type: string
154
+ token_type:
155
+ type: string
156
+ expires_in:
157
+ type: number
158
+ scope:
159
+ type: string
160
+ error:
161
+ type: string
162
+ error_description:
163
+ type: string
164
+
165
+ list:
166
+ input:
167
+ type: object
168
+ properties:
169
+ authority:
170
+ type: string
171
+ identity:
172
+ type: string
173
+ required:
174
+ - authority
175
+ - identity
176
+
177
+ revoke:
178
+ output: { type: 'null' }
179
+ concurrency: retry
180
+ input:
181
+ type: object
182
+ properties:
183
+ authority:
184
+ type: string
185
+ identity:
186
+ type: string
187
+ required:
188
+ - authority
189
+ - identity
190
+ errors:
191
+ - NOT_FOUND
192
+
193
+ configuration:
194
+ schema:
195
+ type: object
196
+ properties:
197
+ lifetime:
198
+ description: Seconds an authorization code may be redeemed within
199
+ type: integer
200
+ minimum: 1
201
+ maximum: 600
202
+ default: 60
203
+ token:
204
+ description: Seconds an access token is valid for; 0 is until it is revoked
205
+ type: integer
206
+ minimum: 0
207
+ default: 2592000
208
+ # both have defaults, so the component reads them without checking
209
+ required: [lifetime, token]
210
+
211
+ stash: ~
212
+
213
+ exposition:
214
+ isolated: true
215
+ /:
216
+ POST:
217
+ anonymous: true
218
+ map:authority: authority
219
+ io:input: [grant_type, code, code_verifier, redirect_uri, client_id, resource]
220
+ io:output: true
221
+ io:status: status
222
+ io:throttle:
223
+ key: ip
224
+ requests: 60
225
+ interval: 60
226
+ cache:exact: no-store
227
+ endpoint: exchange
228
+ /:identity:
229
+ auth:id: identity
230
+ map:authority: authority
231
+ map:segments:
232
+ identity: identity
233
+ GET:
234
+ io:output: [id, client, scope, resource, _created]
235
+ endpoint: list
236
+ POST:
237
+ io:input: [client, redirect, challenge, method, scope, resource]
238
+ io:output: [code, expires_in, error, error_description]
239
+ io:status: status
240
+ cache:exact: no-store
241
+ endpoint: authorize
242
+ /:id:
243
+ DELETE:
244
+ io:output: false
245
+ endpoint: revoke
@@ -0,0 +1,35 @@
1
+ import type { Maybe } from '@toa.io/core';
2
+ import type { Operation } from '@toa.io/bridges.node';
3
+ import type { Context } from './lib/index.js';
4
+ /**
5
+ * What the consent page calls when a user allows a client. The page holds the user's own
6
+ * credentials, so this is the user's own route; the code it answers with is what the client
7
+ * redeems at the token endpoint.
8
+ *
9
+ * The grant is recorded so a user can see what they allowed and take it back. It is not
10
+ * consulted to skip the prompt — consent is asked every time, which is what keeps a client
11
+ * that changed where it wants a code sent from being waved through on an older one.
12
+ */
13
+ export declare class Effect implements Operation {
14
+ private context;
15
+ mount(context: Context): void;
16
+ execute(input: Input): Promise<Maybe<Output>>;
17
+ }
18
+ interface Input {
19
+ authority: string;
20
+ identity: string;
21
+ client: string;
22
+ redirect: string;
23
+ challenge: string;
24
+ method: string;
25
+ scope?: string[];
26
+ resource?: string[];
27
+ }
28
+ interface Output {
29
+ status?: number;
30
+ code?: string;
31
+ expires_in?: number;
32
+ error?: string;
33
+ error_description?: string;
34
+ }
35
+ export {};
@@ -0,0 +1,54 @@
1
+ import { hold, identify } from './lib/index.js';
2
+ /**
3
+ * What the consent page calls when a user allows a client. The page holds the user's own
4
+ * credentials, so this is the user's own route; the code it answers with is what the client
5
+ * redeems at the token endpoint.
6
+ *
7
+ * The grant is recorded so a user can see what they allowed and take it back. It is not
8
+ * consulted to skip the prompt — consent is asked every time, which is what keeps a client
9
+ * that changed where it wants a code sent from being waved through on an older one.
10
+ */
11
+ export class Effect {
12
+ context;
13
+ mount(context) {
14
+ this.context = context;
15
+ }
16
+ async execute(input) {
17
+ const { authority, identity } = input;
18
+ if (input.method !== S256)
19
+ return invalid('invalid_request', 'Only the S256 code challenge method is supported');
20
+ const client = await this.context.remote.identity.clients.describe({
21
+ input: { authority, id: input.client, redirect: input.redirect }
22
+ });
23
+ if (client instanceof Error)
24
+ return invalid('invalid_client', 'No such client');
25
+ if (client.permitted !== true)
26
+ return invalid('invalid_request', 'The redirect is not one this client may receive a code at');
27
+ const scope = input.scope ?? [];
28
+ // recorded on the grant and carried to the token endpoint, and restricting nothing yet:
29
+ // a token carries the rights of the identity that consented, over every path it may
30
+ // reach. What binds it is a `permissions` argument in `exchange`, see documentation/oauth.md
31
+ const resource = input.resource ?? [];
32
+ const grant = await this.context.local.transit({
33
+ query: { id: identify(authority, identity, input.client) },
34
+ input: { authority, identity, client: input.client, scope, resource }
35
+ });
36
+ if (grant instanceof Error)
37
+ return grant;
38
+ const code = await hold(authority, {
39
+ identity,
40
+ client: input.client,
41
+ redirect: input.redirect,
42
+ challenge: input.challenge,
43
+ scope,
44
+ resource
45
+ }, this.context);
46
+ return { code, expires_in: this.context.configuration.lifetime };
47
+ }
48
+ }
49
+ function invalid(error, description) {
50
+ return { status: BAD_REQUEST, error, error_description: description };
51
+ }
52
+ const S256 = 'S256';
53
+ const BAD_REQUEST = 400;
54
+ //# sourceMappingURL=authorize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorize.js","sourceRoot":"","sources":["../source/authorize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAK/C;;;;;;;;GAQG;AACH,MAAM,OAAO,MAAM;IACT,OAAO,CAAU;IAElB,KAAK,CAAE,OAAgB;QAC5B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAEM,KAAK,CAAC,OAAO,CAAE,KAAY;QAChC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAA;QAErC,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI;YACvB,OAAO,OAAO,CAAC,iBAAiB,EAAE,kDAAkD,CAAC,CAAA;QAEvF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;YACjE,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE;SACjE,CAAC,CAAA;QAEF,IAAI,MAAM,YAAY,KAAK;YACzB,OAAO,OAAO,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAA;QAEpD,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI;YAC3B,OAAO,OAAO,CAAC,iBAAiB,EAAE,2DAA2D,CAAC,CAAA;QAEhG,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,EAAE,CAAA;QAE/B,wFAAwF;QACxF,oFAAoF;QACpF,6FAA6F;QAC7F,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAA;QAErC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;YAC7C,KAAK,EAAE,EAAE,EAAE,EAAE,QAAQ,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE;YAC1D,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE;SACtE,CAAC,CAAA;QAEF,IAAI,KAAK,YAAY,KAAK;YACxB,OAAO,KAAK,CAAA;QAEd,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE;YACjC,QAAQ;YACR,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,KAAK;YACL,QAAQ;SACT,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;QAEhB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAA;IAClE,CAAC;CACF;AAED,SAAS,OAAO,CAAE,KAAa,EAAE,WAAmB;IAClD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,CAAA;AACvE,CAAC;AAED,MAAM,IAAI,GAAG,MAAM,CAAA;AACnB,MAAM,WAAW,GAAG,GAAG,CAAA"}
@@ -0,0 +1,37 @@
1
+ import type { Maybe } from '@toa.io/core';
2
+ import type { Operation } from '@toa.io/bridges.node';
3
+ import type { Context } from './lib/index.js';
4
+ /**
5
+ * The token endpoint, RFC 6749 §4.1.3. Anonymous, because the clients this server knows are
6
+ * public ones with no secret to authenticate with: what stands in for that is PKCE, since
7
+ * only the client that began the flow holds the verifier the challenge was made from.
8
+ *
9
+ * Every failure here is `invalid_grant` without saying which check failed. A code that was
10
+ * replayed, a verifier that does not match and a redirect that was swapped are all the same
11
+ * answer, and telling them apart would say whether a stolen code was still live.
12
+ */
13
+ export declare class Effect implements Operation {
14
+ private context;
15
+ mount(context: Context): void;
16
+ execute(input: Input): Promise<Maybe<Output>>;
17
+ private redeemable;
18
+ }
19
+ interface Input {
20
+ authority: string;
21
+ grant_type: string;
22
+ code?: string;
23
+ code_verifier?: string;
24
+ redirect_uri?: string;
25
+ client_id?: string;
26
+ resource?: string | string[];
27
+ }
28
+ interface Output {
29
+ status?: number;
30
+ access_token?: string;
31
+ token_type?: string;
32
+ expires_in?: number;
33
+ scope?: string;
34
+ error?: string;
35
+ error_description?: string;
36
+ }
37
+ export {};
@@ -0,0 +1,89 @@
1
+ import { identify, spend, verifies } from './lib/index.js';
2
+ /**
3
+ * The token endpoint, RFC 6749 §4.1.3. Anonymous, because the clients this server knows are
4
+ * public ones with no secret to authenticate with: what stands in for that is PKCE, since
5
+ * only the client that began the flow holds the verifier the challenge was made from.
6
+ *
7
+ * Every failure here is `invalid_grant` without saying which check failed. A code that was
8
+ * replayed, a verifier that does not match and a redirect that was swapped are all the same
9
+ * answer, and telling them apart would say whether a stolen code was still live.
10
+ */
11
+ export class Effect {
12
+ context;
13
+ mount(context) {
14
+ this.context = context;
15
+ }
16
+ async execute(input) {
17
+ const { authority } = input;
18
+ if (input.grant_type !== AUTHORIZATION_CODE)
19
+ return invalid('unsupported_grant_type', 'Only the authorization code grant is supported');
20
+ if (input.code === undefined || input.code_verifier === undefined)
21
+ return invalid('invalid_request', 'A code and a code verifier are required');
22
+ // spent first: a wrong verifier burns the code, which is what stops it being guessed at
23
+ const code = await spend(authority, input.code, this.context);
24
+ if (code === null || !this.redeemable(code, input))
25
+ return invalid('invalid_grant', 'The authorization code is not redeemable');
26
+ // `permissions` would bind the token to `code.resource` — `{'/mcp/**': ['*']}` for a
27
+ // resource at `/mcp/`, which `permits()` reads on every request. Left unset: the token
28
+ // carries the rights of the identity that consented, see documentation/oauth.md#audience
29
+ const issued = await this.context.remote.identity.tokens.issue({
30
+ input: {
31
+ authority,
32
+ identity: code.identity,
33
+ label: label(code.client),
34
+ lifetime: this.context.configuration.token,
35
+ ...(code.scope.length === 0 ? {} : { scopes: code.scope })
36
+ }
37
+ });
38
+ // the only refusal `issue` makes is a scope the consenting identity does not hold, and
39
+ // what it says about that is its own; the client is told what it may act on
40
+ if (issued instanceof Error)
41
+ return invalid('invalid_scope', 'The requested scope is not one the identity holds');
42
+ // the key the token was issued under, so revoking the grant revokes the token. The token
43
+ // is already out, so a grant that fails to record it is logged rather than unwound — it
44
+ // costs the user the ability to revoke, and refusing here would cost them the token too
45
+ const grant = await this.context.local.transit({
46
+ query: { id: identify(authority, code.identity, code.client) },
47
+ input: {
48
+ authority,
49
+ identity: code.identity,
50
+ client: code.client,
51
+ scope: code.scope,
52
+ resource: code.resource,
53
+ kid: issued.kid
54
+ }
55
+ });
56
+ if (grant instanceof Error)
57
+ this.context.logs.error('Grant not recorded for an issued token', { client: code.client, kid: issued.kid });
58
+ return {
59
+ // RFC 6749 §5.1 asks for 200, where a POST would otherwise answer 201
60
+ status: OK,
61
+ access_token: issued.token,
62
+ token_type: 'Bearer',
63
+ ...(issued.exp === undefined
64
+ ? {}
65
+ : { expires_in: Math.floor((issued.exp - Date.now()) / 1000) }),
66
+ ...(code.scope.length === 0 ? {} : { scope: code.scope.join(' ') })
67
+ };
68
+ }
69
+ redeemable(code, input) {
70
+ if (!verifies(code.challenge, input.code_verifier))
71
+ return false;
72
+ // RFC 6749 §4.1.3: what was sent to `authorize` must be sent again
73
+ if (input.redirect_uri !== undefined && input.redirect_uri !== code.redirect)
74
+ return false;
75
+ return input.client_id === undefined || input.client_id === code.client;
76
+ }
77
+ }
78
+ /** `identity.tokens` requires one, and it is what a user sees when listing what they issued. */
79
+ function label(client) {
80
+ return client.slice(0, LABEL);
81
+ }
82
+ function invalid(error, description) {
83
+ return { status: BAD_REQUEST, error, error_description: description };
84
+ }
85
+ const AUTHORIZATION_CODE = 'authorization_code';
86
+ const OK = 200;
87
+ const BAD_REQUEST = 400;
88
+ const LABEL = 64;
89
+ //# sourceMappingURL=exchange.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exchange.js","sourceRoot":"","sources":["../source/exchange.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { Code, Context } from '../../types/index.js';
2
+ /**
3
+ * An authorization code is a bearer credential that lives for seconds. It is held under a
4
+ * hash of itself, so a dump of the store hands out none of them, and redeemed with `GETDEL`,
5
+ * so it is spent once however many requests arrive at once — the property the whole flow
6
+ * rests on, since a replayed code is a stolen grant.
7
+ */
8
+ export declare function hold(authority: string, code: Code, context: Context): Promise<string>;
9
+ export declare function spend(authority: string, value: string, context: Context): Promise<Code | null>;
10
+ /**
11
+ * PKCE, RFC 7636: the client kept a verifier and sent its hash, and only the client that
12
+ * began the flow can present the verifier now. `S256` alone — `plain` proves nothing.
13
+ */
14
+ export declare function verifies(challenge: string, verifier: string): boolean;
15
+ export declare function digest(verifier: string): string;
@@ -0,0 +1,30 @@
1
+ import { createHash, randomBytes } from 'node:crypto';
2
+ /**
3
+ * An authorization code is a bearer credential that lives for seconds. It is held under a
4
+ * hash of itself, so a dump of the store hands out none of them, and redeemed with `GETDEL`,
5
+ * so it is spent once however many requests arrive at once — the property the whole flow
6
+ * rests on, since a replayed code is a stolen grant.
7
+ */
8
+ export async function hold(authority, code, context) {
9
+ const value = randomBytes(32).toString('base64url');
10
+ await context.stash.set(key(authority, value), JSON.stringify(code), 'EX', context.configuration.lifetime);
11
+ return value;
12
+ }
13
+ export async function spend(authority, value, context) {
14
+ const held = await context.stash.getdel(key(authority, value));
15
+ return held === null ? null : JSON.parse(held);
16
+ }
17
+ /**
18
+ * PKCE, RFC 7636: the client kept a verifier and sent its hash, and only the client that
19
+ * began the flow can present the verifier now. `S256` alone — `plain` proves nothing.
20
+ */
21
+ export function verifies(challenge, verifier) {
22
+ return digest(verifier) === challenge;
23
+ }
24
+ export function digest(verifier) {
25
+ return createHash('sha256').update(verifier).digest('base64url');
26
+ }
27
+ function key(authority, value) {
28
+ return `oauth:code:${authority}:${createHash('sha256').update(value).digest('hex')}`;
29
+ }
30
+ //# sourceMappingURL=code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code.js","sourceRoot":"","sources":["../../source/lib/code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGrD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CAAE,SAAiB,EAAE,IAAU,EAAE,OAAgB;IACzE,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;IAEnD,MAAM,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EACjE,IAAI,EAAE,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;IAEvC,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,KAAK,CAAE,SAAiB,EAAE,KAAa,EAAE,OAAgB;IAC7E,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAA;IAE9D,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAS,CAAA;AACxD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAE,SAAiB,EAAE,QAAgB;IAC3D,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,SAAS,CAAA;AACvC,CAAC;AAED,MAAM,UAAU,MAAM,CAAE,QAAgB;IACtC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;AAClE,CAAC;AAED,SAAS,GAAG,CAAE,SAAiB,EAAE,KAAa;IAC5C,OAAO,cAAc,SAAS,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAA;AACtF,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * A user holds one grant per client, so the record is addressed by the three things that
3
+ * say which: authorizing again replaces what is there rather than leaving another row, and
4
+ * revoking has one thing to revoke.
5
+ */
6
+ export declare function identify(authority: string, identity: string, client: string): string;
@@ -0,0 +1,15 @@
1
+ import { createHash } from 'node:crypto';
2
+ /**
3
+ * A user holds one grant per client, so the record is addressed by the three things that
4
+ * say which: authorizing again replaces what is there rather than leaving another row, and
5
+ * revoking has one thing to revoke.
6
+ */
7
+ export function identify(authority, identity, client) {
8
+ return createHash('sha256')
9
+ .update(JSON.stringify([authority, identity, client]))
10
+ .digest('hex')
11
+ .slice(0, LENGTH);
12
+ }
13
+ /** What the entity prototype accepts as an id. */
14
+ const LENGTH = 32;
15
+ //# sourceMappingURL=identify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identify.js","sourceRoot":"","sources":["../../source/lib/identify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAE,SAAiB,EAAE,QAAgB,EAAE,MAAc;IAC3E,OAAO,UAAU,CAAC,QAAQ,CAAC;SACxB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;SACrD,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;AACrB,CAAC;AAED,kDAAkD;AAClD,MAAM,MAAM,GAAG,EAAE,CAAA"}