@things-factory/auth-base 10.1.278 → 10.1.280

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 (284) hide show
  1. package/package.json +24 -7
  2. package/CHANGELOG.md +0 -55
  3. package/dist-client/actions/auth.js.map +0 -1
  4. package/dist-client/apply-domain-theme.js.map +0 -1
  5. package/dist-client/auth.js.map +0 -1
  6. package/dist-client/bootstrap.js.map +0 -1
  7. package/dist-client/directive/privileged.js.map +0 -1
  8. package/dist-client/domain-required.js.map +0 -1
  9. package/dist-client/index.js.map +0 -1
  10. package/dist-client/profiled.js.map +0 -1
  11. package/dist-client/reducers/auth.js.map +0 -1
  12. package/dist-client/tsconfig.tsbuildinfo +0 -1
  13. package/dist-client/verify-webauthn.js.map +0 -1
  14. package/dist-server/ai-entry/access-assistant.js.map +0 -1
  15. package/dist-server/ai-entry/access-entry-targets.js.map +0 -1
  16. package/dist-server/ai-entry/entry-target-shape.js.map +0 -1
  17. package/dist-server/constants/error-code.js.map +0 -1
  18. package/dist-server/constants/error-message.js.map +0 -1
  19. package/dist-server/constants/max-age.js.map +0 -1
  20. package/dist-server/controllers/access-request.js.map +0 -1
  21. package/dist-server/controllers/account-mail.js.map +0 -1
  22. package/dist-server/controllers/auth.js.map +0 -1
  23. package/dist-server/controllers/change-pwd.js.map +0 -1
  24. package/dist-server/controllers/confirm-identity.js.map +0 -1
  25. package/dist-server/controllers/delete-user.js.map +0 -1
  26. package/dist-server/controllers/passkey.js.map +0 -1
  27. package/dist-server/controllers/password-setup.js.map +0 -1
  28. package/dist-server/controllers/profile.js.map +0 -1
  29. package/dist-server/controllers/reset-password.js.map +0 -1
  30. package/dist-server/controllers/signin.js.map +0 -1
  31. package/dist-server/controllers/signup.js.map +0 -1
  32. package/dist-server/controllers/unlock-user.js.map +0 -1
  33. package/dist-server/controllers/utils/find-verification-token.js.map +0 -1
  34. package/dist-server/controllers/utils/make-verification-token.js.map +0 -1
  35. package/dist-server/controllers/utils/password-rule.js.map +0 -1
  36. package/dist-server/controllers/utils/save-verification-token.js.map +0 -1
  37. package/dist-server/controllers/verification.js.map +0 -1
  38. package/dist-server/errors/auth-error.js.map +0 -1
  39. package/dist-server/errors/index.js.map +0 -1
  40. package/dist-server/errors/user-domain-not-match-error.js.map +0 -1
  41. package/dist-server/index.js.map +0 -1
  42. package/dist-server/middlewares/audit-scope-middleware.js.map +0 -1
  43. package/dist-server/middlewares/authenticate-401-middleware.js.map +0 -1
  44. package/dist-server/middlewares/bypass-signin-middleware.js.map +0 -1
  45. package/dist-server/middlewares/domain-authenticate-middleware.js.map +0 -1
  46. package/dist-server/middlewares/graphql-authenticate-middleware.js.map +0 -1
  47. package/dist-server/middlewares/index.js.map +0 -1
  48. package/dist-server/middlewares/jwt-authenticate-middleware.js.map +0 -1
  49. package/dist-server/middlewares/signin-middleware.js.map +0 -1
  50. package/dist-server/middlewares/verify-recaptcha-middleware.js.map +0 -1
  51. package/dist-server/migrations/1548206416130-SeedUser.js.map +0 -1
  52. package/dist-server/migrations/1566805283882-SeedPrivilege.js.map +0 -1
  53. package/dist-server/migrations/1745000000000-MigrateDomainOwnersToTable.js.map +0 -1
  54. package/dist-server/migrations/index.js.map +0 -1
  55. package/dist-server/role-tasks.js.map +0 -1
  56. package/dist-server/router/auth-checkin-router.js.map +0 -1
  57. package/dist-server/router/auth-private-process-router.js.map +0 -1
  58. package/dist-server/router/auth-public-process-router.js.map +0 -1
  59. package/dist-server/router/auth-signin-router.js.map +0 -1
  60. package/dist-server/router/auth-signup-router.js.map +0 -1
  61. package/dist-server/router/index.js.map +0 -1
  62. package/dist-server/router/oauth2/index.js.map +0 -1
  63. package/dist-server/router/oauth2/oauth2-authorize-router.js.map +0 -1
  64. package/dist-server/router/oauth2/oauth2-router.js.map +0 -1
  65. package/dist-server/router/oauth2/oauth2-server.js.map +0 -1
  66. package/dist-server/router/oauth2/passport-oauth2-client-password.js.map +0 -1
  67. package/dist-server/router/oauth2/passport-refresh-token.js.map +0 -1
  68. package/dist-server/router/path-base-domain-router.js.map +0 -1
  69. package/dist-server/router/site-root-router.js.map +0 -1
  70. package/dist-server/router/webauthn-router.js.map +0 -1
  71. package/dist-server/routes.js.map +0 -1
  72. package/dist-server/service/access-request/access-request-mutation.js.map +0 -1
  73. package/dist-server/service/access-request/access-request-query.js.map +0 -1
  74. package/dist-server/service/access-request/access-request-types.js.map +0 -1
  75. package/dist-server/service/access-request/access-request.js.map +0 -1
  76. package/dist-server/service/access-request/index.js.map +0 -1
  77. package/dist-server/service/app-binding/app-binding-mutation.js.map +0 -1
  78. package/dist-server/service/app-binding/app-binding-query.js.map +0 -1
  79. package/dist-server/service/app-binding/app-binding-types.js.map +0 -1
  80. package/dist-server/service/app-binding/app-binding.js.map +0 -1
  81. package/dist-server/service/app-binding/index.js.map +0 -1
  82. package/dist-server/service/appliance/appliance-mutation.js.map +0 -1
  83. package/dist-server/service/appliance/appliance-query.js.map +0 -1
  84. package/dist-server/service/appliance/appliance-types.js.map +0 -1
  85. package/dist-server/service/appliance/appliance.js.map +0 -1
  86. package/dist-server/service/appliance/index.js.map +0 -1
  87. package/dist-server/service/application/application-mutation.js.map +0 -1
  88. package/dist-server/service/application/application-query.js.map +0 -1
  89. package/dist-server/service/application/application-types.js.map +0 -1
  90. package/dist-server/service/application/application.js.map +0 -1
  91. package/dist-server/service/application/index.js.map +0 -1
  92. package/dist-server/service/audit/audit-action.js.map +0 -1
  93. package/dist-server/service/audit/audit-kinds.js.map +0 -1
  94. package/dist-server/service/audit/audit-query.js.map +0 -1
  95. package/dist-server/service/audit/audit-recorder.js.map +0 -1
  96. package/dist-server/service/audit/audit-request.js.map +0 -1
  97. package/dist-server/service/audit/audit-retention.js.map +0 -1
  98. package/dist-server/service/audit/audit-subscriber.js.map +0 -1
  99. package/dist-server/service/audit/audit-target.js.map +0 -1
  100. package/dist-server/service/audit/audit-types.js.map +0 -1
  101. package/dist-server/service/audit/audit-work.js.map +0 -1
  102. package/dist-server/service/audit/index.js.map +0 -1
  103. package/dist-server/service/auth-provider/auth-provider-mutation.js.map +0 -1
  104. package/dist-server/service/auth-provider/auth-provider-parameter-spec.js.map +0 -1
  105. package/dist-server/service/auth-provider/auth-provider-query.js.map +0 -1
  106. package/dist-server/service/auth-provider/auth-provider-type.js.map +0 -1
  107. package/dist-server/service/auth-provider/auth-provider.js.map +0 -1
  108. package/dist-server/service/auth-provider/index.js.map +0 -1
  109. package/dist-server/service/domain-generator/domain-generator-mutation.js.map +0 -1
  110. package/dist-server/service/domain-generator/domain-generator-types.js.map +0 -1
  111. package/dist-server/service/domain-generator/index.js.map +0 -1
  112. package/dist-server/service/domain-link/domain-link-mutation.js.map +0 -1
  113. package/dist-server/service/domain-link/domain-link-query.js.map +0 -1
  114. package/dist-server/service/domain-link/domain-link-types.js.map +0 -1
  115. package/dist-server/service/domain-link/domain-link.js.map +0 -1
  116. package/dist-server/service/domain-link/index.js.map +0 -1
  117. package/dist-server/service/domain-owner/domain-owner-mutation.js.map +0 -1
  118. package/dist-server/service/domain-owner/domain-owner-query.js.map +0 -1
  119. package/dist-server/service/domain-owner/domain-owner.js.map +0 -1
  120. package/dist-server/service/domain-owner/index.js.map +0 -1
  121. package/dist-server/service/granted-role/granted-role-mutation.js.map +0 -1
  122. package/dist-server/service/granted-role/granted-role-query.js.map +0 -1
  123. package/dist-server/service/granted-role/granted-role.js.map +0 -1
  124. package/dist-server/service/granted-role/index.js.map +0 -1
  125. package/dist-server/service/identity-confirmation/identity-confirmation.js.map +0 -1
  126. package/dist-server/service/index.js.map +0 -1
  127. package/dist-server/service/open-fields.js.map +0 -1
  128. package/dist-server/service/partner/index.js.map +0 -1
  129. package/dist-server/service/partner/partner-mutation.js.map +0 -1
  130. package/dist-server/service/partner/partner-query.js.map +0 -1
  131. package/dist-server/service/partner/partner-types.js.map +0 -1
  132. package/dist-server/service/partner/partner.js.map +0 -1
  133. package/dist-server/service/password-history/index.js.map +0 -1
  134. package/dist-server/service/password-history/password-history.js.map +0 -1
  135. package/dist-server/service/privilege/index.js.map +0 -1
  136. package/dist-server/service/privilege/open-field-rule.js.map +0 -1
  137. package/dist-server/service/privilege/privilege-axis.js.map +0 -1
  138. package/dist-server/service/privilege/privilege-deprecation.js.map +0 -1
  139. package/dist-server/service/privilege/privilege-directive.js.map +0 -1
  140. package/dist-server/service/privilege/privilege-mutation.js.map +0 -1
  141. package/dist-server/service/privilege/privilege-query.js.map +0 -1
  142. package/dist-server/service/privilege/privilege-rejection.js.map +0 -1
  143. package/dist-server/service/privilege/privilege-sync.js.map +0 -1
  144. package/dist-server/service/privilege/privilege-types.js.map +0 -1
  145. package/dist-server/service/privilege/privilege.js.map +0 -1
  146. package/dist-server/service/role/index.js.map +0 -1
  147. package/dist-server/service/role/role-mutation.js.map +0 -1
  148. package/dist-server/service/role/role-privilege-query.js.map +0 -1
  149. package/dist-server/service/role/role-query.js.map +0 -1
  150. package/dist-server/service/role/role-types.js.map +0 -1
  151. package/dist-server/service/role/role.js.map +0 -1
  152. package/dist-server/service/role-template/index.js.map +0 -1
  153. package/dist-server/service/role-template/role-task.js.map +0 -1
  154. package/dist-server/service/role-template/role-template-gap-resolver.js.map +0 -1
  155. package/dist-server/service/role-template/role-template-mutation.js.map +0 -1
  156. package/dist-server/service/role-template/role-template-query.js.map +0 -1
  157. package/dist-server/service/role-template/role-template-types.js.map +0 -1
  158. package/dist-server/service/role-template/role-template.js.map +0 -1
  159. package/dist-server/service/user/domain-query.js.map +0 -1
  160. package/dist-server/service/user/index.js.map +0 -1
  161. package/dist-server/service/user/user-mutation.js.map +0 -1
  162. package/dist-server/service/user/user-query.js.map +0 -1
  163. package/dist-server/service/user/user-types.js.map +0 -1
  164. package/dist-server/service/user/user.js.map +0 -1
  165. package/dist-server/service/users-auth-providers/index.js.map +0 -1
  166. package/dist-server/service/users-auth-providers/users-auth-providers.js.map +0 -1
  167. package/dist-server/service/verification-token/index.js.map +0 -1
  168. package/dist-server/service/verification-token/verification-token.js.map +0 -1
  169. package/dist-server/service/web-auth-credential/index.js.map +0 -1
  170. package/dist-server/service/web-auth-credential/web-auth-credential-mutation.js.map +0 -1
  171. package/dist-server/service/web-auth-credential/web-auth-credential-query.js.map +0 -1
  172. package/dist-server/service/web-auth-credential/web-auth-credential.js.map +0 -1
  173. package/dist-server/tsconfig.tsbuildinfo +0 -1
  174. package/dist-server/types.js.map +0 -1
  175. package/dist-server/utils/accepts.js.map +0 -1
  176. package/dist-server/utils/access-request-review.js.map +0 -1
  177. package/dist-server/utils/access-token-cookie.js.map +0 -1
  178. package/dist-server/utils/account-lock-rule.js.map +0 -1
  179. package/dist-server/utils/assignable-roles.js.map +0 -1
  180. package/dist-server/utils/build-auth-url.js.map +0 -1
  181. package/dist-server/utils/can-user-checkin-domain.js.map +0 -1
  182. package/dist-server/utils/check-permission.js.map +0 -1
  183. package/dist-server/utils/check-user-belongs-domain.js.map +0 -1
  184. package/dist-server/utils/check-user-has-role.js.map +0 -1
  185. package/dist-server/utils/checkin-domain-facts.js.map +0 -1
  186. package/dist-server/utils/checkin-domain-rule.js.map +0 -1
  187. package/dist-server/utils/credential-at-rest.js.map +0 -1
  188. package/dist-server/utils/credential-features.js.map +0 -1
  189. package/dist-server/utils/credential-serial-rule.js.map +0 -1
  190. package/dist-server/utils/domain-ownership.js.map +0 -1
  191. package/dist-server/utils/encrypt-state.js.map +0 -1
  192. package/dist-server/utils/get-aes-256-key.js.map +0 -1
  193. package/dist-server/utils/get-domain-users.js.map +0 -1
  194. package/dist-server/utils/get-secret.js.map +0 -1
  195. package/dist-server/utils/get-user-domains.js.map +0 -1
  196. package/dist-server/utils/lock-duration.js.map +0 -1
  197. package/dist-server/utils/password-reset-rule.js.map +0 -1
  198. package/dist-server/utils/profile-user.js.map +0 -1
  199. package/dist-server/utils/refuse-role-name.js.map +0 -1
  200. package/dist-server/utils/role-name-standing.js.map +0 -1
  201. package/dist-server/utils/same-origin-redirect.js.map +0 -1
  202. package/dist-server/utils/verification-token-rule.js.map +0 -1
  203. package/spec/unit/checkin-domain.spec.ts +0 -307
  204. package/spec/unit/checkin-privilege.spec.ts +0 -205
  205. package/spec/unit/domain-owner-entity.spec.ts +0 -179
  206. package/spec/unit/domain-owner-granted.spec.ts +0 -215
  207. package/spec/unit/domain-owner-migration.spec.ts +0 -236
  208. package/spec/unit/domain-owner-mutation.spec.ts +0 -337
  209. package/spec/unit/domain-ownership.spec.ts +0 -188
  210. package/tests/access-assistant-db.test.ts +0 -155
  211. package/tests/access-entry-targets-db.test.ts +0 -176
  212. package/tests/access-request-db.test.ts +0 -394
  213. package/tests/access-request-pg.test.ts +0 -83
  214. package/tests/access-request-review.test.ts +0 -193
  215. package/tests/account-lock-db.test.ts +0 -216
  216. package/tests/account-lock-rule.test.ts +0 -141
  217. package/tests/account-mail.test.ts +0 -69
  218. package/tests/activate-page-case.test.ts +0 -53
  219. package/tests/add-user-gates.test.ts +0 -34
  220. package/tests/app-binding-db.test.ts +0 -210
  221. package/tests/app-binding-delete-db.test.ts +0 -188
  222. package/tests/appliance-credential-state-db.test.ts +0 -207
  223. package/tests/appliance-delete-db.test.ts +0 -119
  224. package/tests/appliance-revoke-db.test.ts +0 -294
  225. package/tests/appliance-schema.test.ts +0 -129
  226. package/tests/application-delete-db.test.ts +0 -190
  227. package/tests/application-token-payload-db.test.ts +0 -185
  228. package/tests/assignable-roles-db.test.ts +0 -219
  229. package/tests/audit-db.test.ts +0 -410
  230. package/tests/audit-work.test.ts +0 -58
  231. package/tests/auth-base-role-tasks.test.ts +0 -58
  232. package/tests/checkin-domain-rule.test.ts +0 -128
  233. package/tests/checkin-privilege-seam-db.test.ts +0 -158
  234. package/tests/compiled.ts +0 -41
  235. package/tests/confirm-identity-db.test.ts +0 -85
  236. package/tests/credential-at-rest-db.test.ts +0 -246
  237. package/tests/credential-features-off-db.test.ts +0 -189
  238. package/tests/credential-serial-rule.test.ts +0 -84
  239. package/tests/declare-privileges.test.ts +0 -29
  240. package/tests/domain-assignees-db.test.ts +0 -95
  241. package/tests/domain-inheritance-sentinel.test.ts +0 -93
  242. package/tests/domain-required.test.ts +0 -127
  243. package/tests/has-privilege-db.test.ts +0 -198
  244. package/tests/identity-confirmation.test.ts +0 -146
  245. package/tests/list-inheritance-db.test.ts +0 -127
  246. package/tests/lock-recovery.test.ts +0 -206
  247. package/tests/mail-request-answers-db.test.ts +0 -142
  248. package/tests/open-doors.test.ts +0 -121
  249. package/tests/open-fields-enforcement.test.ts +0 -215
  250. package/tests/open-fields-framework.test.ts +0 -212
  251. package/tests/open-redirect-db.test.ts +0 -143
  252. package/tests/passkey-authenticator.ts +0 -104
  253. package/tests/passkey-db.test.ts +0 -295
  254. package/tests/passkey-signin-route-db.test.ts +0 -139
  255. package/tests/password-hashing.test.ts +0 -131
  256. package/tests/password-persistence.test.ts +0 -147
  257. package/tests/password-reset-rule-db.test.ts +0 -159
  258. package/tests/password-setup-db.test.ts +0 -215
  259. package/tests/permission-gate.test.ts +0 -228
  260. package/tests/picture-reducer.test.ts +0 -25
  261. package/tests/privilege-axis.test.ts +0 -157
  262. package/tests/privilege-deprecation.test.ts +0 -65
  263. package/tests/privilege-directive.test.ts +0 -332
  264. package/tests/privilege-rejection.test.ts +0 -104
  265. package/tests/privilege-sync-db.test.ts +0 -58
  266. package/tests/profile-user.test.ts +0 -24
  267. package/tests/refusal-cause.test.ts +0 -80
  268. package/tests/refusals-have-korean.test.ts +0 -24
  269. package/tests/request-holds.test.ts +0 -53
  270. package/tests/role-inheritance-db.test.ts +0 -286
  271. package/tests/role-mutation-db.test.ts +0 -293
  272. package/tests/role-name-lookup-sentinel.test.ts +0 -79
  273. package/tests/role-name-standing.test.ts +0 -83
  274. package/tests/role-privileges-db.test.ts +0 -252
  275. package/tests/role-task.test.ts +0 -168
  276. package/tests/role-template-gap-db.test.ts +0 -268
  277. package/tests/role-template-seed-db.test.ts +0 -180
  278. package/tests/role-template.test.ts +0 -162
  279. package/tests/role-users-gate.test.ts +0 -22
  280. package/tests/signin-policy.test.ts +0 -200
  281. package/tests/signup-duplicate-db.test.ts +0 -68
  282. package/tests/token-issuance.test.ts +0 -244
  283. package/tests/user-roles-field-db.test.ts +0 -134
  284. package/tests/verification-token-db.test.ts +0 -285
@@ -1 +0,0 @@
1
- {"version":3,"file":"domain-link-types.js","sourceRoot":"","sources":["../../../server/service/domain-link/domain-link-types.ts"],"names":[],"mappings":";;;;AAAA,+CAAoE;AAEpE,iDAAiD;AAEjD,qDAA6D;AAGtD,IAAM,aAAa,GAAnB,MAAM,aAAa;CASzB,CAAA;AATY,sCAAa;AAExB;IADC,IAAA,oBAAK,EAAC,GAAG,EAAE,CAAC,iBAAS,EAAE,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;sCACpE,iBAAS;mDAAA;AAGvB;IADC,IAAA,oBAAK,EAAC,GAAG,EAAE,CAAC,iBAAS,EAAE,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;sCACpE,iBAAS;mDAAA;AAGvB;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,+BAA+B,EAAE,CAAC;;2CACpC;wBART,aAAa;IADzB,IAAA,wBAAS,EAAC,EAAE,WAAW,EAAE,uCAAuC,EAAE,CAAC;GACvD,aAAa,CASzB;AAGM,IAAM,eAAe,GAArB,MAAM,eAAe;CAe3B,CAAA;AAfY,0CAAe;AAE1B;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAE,EAAE,EAAE,WAAW,EAAE,qDAAqD,EAAE,CAAC;;2CAC/E;AAGX;IADC,IAAA,oBAAK,EAAC,GAAG,EAAE,CAAC,iBAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,6CAA6C,EAAE,CAAC;sCACzF,iBAAS;qDAAA;AAGvB;IADC,IAAA,oBAAK,EAAC,GAAG,EAAE,CAAC,iBAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,6CAA6C,EAAE,CAAC;sCACzF,iBAAS;qDAAA;AAGvB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,oCAAoC,EAAE,CAAC;;6CACzD;AAGpB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,2EAA2E,EAAE,CAAC;;+CACrG;0BAdJ,eAAe;IAD3B,IAAA,wBAAS,EAAC,EAAE,WAAW,EAAE,wDAAwD,EAAE,CAAC;GACxE,eAAe,CAe3B;AAGM,IAAM,cAAc,GAApB,MAAM,cAAc;CAM1B,CAAA;AANY,wCAAc;AAEzB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,2BAAU,CAAC,EAAE,EAAE,WAAW,EAAE,gCAAgC,EAAE,CAAC;;6CAC5D;AAGnB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,WAAW,EAAE,mCAAmC,EAAE,CAAC;;6CAC5D;yBALF,cAAc;IAD1B,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,mCAAmC,EAAE,CAAC;GACpD,cAAc,CAM1B","sourcesContent":["import { ObjectType, Field, InputType, Int, ID } from 'type-graphql'\n\nimport { ObjectRef } from '@things-factory/shell'\n\nimport { DomainLink, DomainLinkType } from './domain-link.js'\n\n@InputType({ description: 'Input for creating a new domain link.' })\nexport class NewDomainLink {\n @Field(() => ObjectRef, { description: 'The source domain in the relationship.' })\n sourceDomain: ObjectRef\n\n @Field(() => ObjectRef, { description: 'The target domain in the relationship.' })\n targetDomain: ObjectRef\n\n @Field({ description: 'The type of the relationship.' })\n type: DomainLinkType\n}\n\n@InputType({ description: 'Input for updating (patching) an existing domain link.' })\nexport class DomainLinkPatch {\n @Field(type => ID, { description: 'The unique identifier of the domain link to update.' })\n id?: string\n\n @Field(() => ObjectRef, { nullable: true, description: 'The new source domain for the relationship.' })\n sourceDomain: ObjectRef\n\n @Field(() => ObjectRef, { nullable: true, description: 'The new target domain for the relationship.' })\n targetDomain: ObjectRef\n\n @Field({ nullable: true, description: 'The new type for the relationship.' })\n type: DomainLinkType\n\n @Field({ nullable: true, description: 'A flag indicating whether the link is being created, updated, or deleted.' })\n cuFlag?: string\n}\n\n@ObjectType({ description: 'A paginated list of domain links.' })\nexport class DomainLinkList {\n @Field(type => [DomainLink], { description: 'The list of domain link items.' })\n items: DomainLink[]\n\n @Field(type => Int, { description: 'The total number of domain links.' })\n total: number\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"domain-link.js","sourceRoot":"","sources":["../../../server/service/domain-link/domain-link.ts"],"names":[],"mappings":";;;;AAAA,qCASgB;AAChB,+CAAsE;AAEtE,6CAA4C;AAC5C,iDAA8C;AAC9C,6CAAsC;AAEtC,MAAM,SAAS,GAAG,YAAM,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;AAC7C,MAAM,aAAa,GAAG,SAAS,CAAC,IAAI,CAAA;AAEpC,IAAY,cAIX;AAJD,WAAY,cAAc;IACxB,6BAAW,CAAA;IACX,yCAAuB,CAAA;IACvB,+BAAa,CAAA,CAAC,wCAAwC;AACxD,CAAC,EAJW,cAAc,8BAAd,cAAc,QAIzB;AAED,IAAA,+BAAgB,EAAC,cAAc,EAAE;IAC/B,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,oDAAoD;CAClE,CAAC,CAAA;AAWK,IAAM,UAAU,GAAhB,MAAM,UAAU;CAkEtB,CAAA;AAlEY,gCAAU;AAGZ;IAFR,IAAA,gCAAsB,EAAC,MAAM,CAAC;IAC9B,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAE,EAAE,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;;sCAC1D;AAKnB;IAFC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,cAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IACjE,IAAA,oBAAK,EAAC,GAAG,EAAE,CAAC,cAAM,EAAE,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;sCACjE,cAAM;gDAAA;AAGpB;IADC,IAAA,oBAAU,EAAC,CAAC,UAAsB,EAAE,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC;;kDAC1C;AAKtB;IAFC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,cAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IACjE,IAAA,oBAAK,EAAC,GAAG,EAAE,CAAC,cAAM,EAAE,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;sCACjE,cAAM;gDAAA;AAGpB;IADC,IAAA,oBAAU,EAAC,CAAC,UAAsB,EAAE,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC;;kDAC1C;AAoBtB;IAjBC,IAAA,gBAAM,EAAC;QACN,IAAI,EACF,aAAa,IAAI,UAAU,IAAI,aAAa,IAAI,OAAO,IAAI,aAAa,IAAI,SAAS;YACnF,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,aAAa,IAAI,QAAQ;gBACzB,CAAC,CAAC,UAAU;gBACZ,CAAC,CAAC,aAAa,IAAI,OAAO;oBACxB,CAAC,CAAC,UAAU;oBACZ,CAAC,CAAC,SAAS;QACnB,IAAI,EACF,aAAa,IAAI,UAAU,IAAI,aAAa,IAAI,OAAO,IAAI,aAAa,IAAI,SAAS;YACnF,CAAC,CAAC,cAAc;YAChB,CAAC,CAAC,SAAS;QACf,MAAM,EAAE,aAAa,IAAI,UAAU,IAAI,aAAa,IAAI,OAAO,IAAI,aAAa,IAAI,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;QAC9G,OAAO,EAAE,cAAc,CAAC,GAAG;KAC5B,CAAC;IACD,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,4DAA4D,EAAE,CAAC;;wCACjE;AAKpB;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,iDAAiD,EAAE,CAAC;sCAC/D,IAAI;IAEf,4BAA4B;;6CAFb;AAKf;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,sDAAsD,EAAE,CAAC;sCACpE,IAAI;IAEf,mBAAmB;;6CAFJ;AAKf;IAFC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,cAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACzC,IAAA,oBAAK,EAAC,GAAG,EAAE,CAAC,cAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,uCAAuC,EAAE,CAAC;sCAClF,cAAI;2CAAA;AAGd;IADC,IAAA,oBAAU,EAAC,CAAC,UAAsB,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;;6CACzC;AAKlB;IAFC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,cAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACzC,IAAA,oBAAK,EAAC,GAAG,EAAE,CAAC,cAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,4CAA4C,EAAE,CAAC;sCACvF,cAAI;2CAAA;AAGd;IADC,IAAA,oBAAU,EAAC,CAAC,UAAsB,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;;6CACzC;qBAjEP,UAAU;IATtB,IAAA,gBAAM,GAAE;IACR,IAAA,eAAK,EACJ,uBAAuB,EACvB,CAAC,UAAsB,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,YAAY,EAAE,UAAU,CAAC,YAAY,EAAE,UAAU,CAAC,IAAI,CAAC,EAC/F,EAAE,MAAM,EAAE,IAAI,EAAE,CACjB;IACA,IAAA,eAAK,EAAC,uBAAuB,EAAE,CAAC,UAAsB,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;IACrF,IAAA,eAAK,EAAC,uBAAuB,EAAE,CAAC,UAAsB,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;IACrF,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,sDAAsD,EAAE,CAAC;GACvE,UAAU,CAkEtB","sourcesContent":["import {\n CreateDateColumn,\n UpdateDateColumn,\n Entity,\n Index,\n Column,\n RelationId,\n ManyToOne,\n PrimaryGeneratedColumn\n} from 'typeorm'\nimport { ObjectType, Field, ID, registerEnumType } from 'type-graphql'\n\nimport { config } from '@things-factory/env'\nimport { Domain } from '@things-factory/shell'\nimport { User } from '../user/user.js'\n\nconst ORMCONFIG = config.get('ormconfig', {})\nconst DATABASE_TYPE = ORMCONFIG.type\n\nexport enum DomainLinkType {\n has = 'has', // Represents a general association or membership.\n maintains = 'maintains', // Represents a relationship where the source domain manages or maintains the target domain.\n owns = 'owns' // Represents an ownership relationship.\n}\n\nregisterEnumType(DomainLinkType, {\n name: 'DomainLinkType',\n description: 'Enumeration of relationship types between domains.'\n})\n\n@Entity()\n@Index(\n 'ix_domain_link_unique',\n (domainLink: DomainLink) => [domainLink.sourceDomain, domainLink.targetDomain, domainLink.type],\n { unique: true }\n)\n@Index('ix_domain_link_source', (domainLink: DomainLink) => [domainLink.sourceDomain])\n@Index('ix_domain_link_target', (domainLink: DomainLink) => [domainLink.targetDomain])\n@ObjectType({ description: 'Represents a typed relationship between two domains.' })\nexport class DomainLink {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier for the domain link.' })\n readonly id: string\n\n /** Source Domain */\n @ManyToOne(() => Domain, { nullable: false, onDelete: 'CASCADE' })\n @Field(() => Domain, { description: 'The source domain in the relationship.' })\n sourceDomain: Domain\n\n @RelationId((domainLink: DomainLink) => domainLink.sourceDomain)\n sourceDomainId: string\n\n /** Target Domain */\n @ManyToOne(() => Domain, { nullable: false, onDelete: 'CASCADE' })\n @Field(() => Domain, { description: 'The target domain in the relationship.' })\n targetDomain: Domain\n\n @RelationId((domainLink: DomainLink) => domainLink.targetDomain)\n targetDomainId: string\n\n /** Link Type */\n @Column({\n type:\n DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? 'enum'\n : DATABASE_TYPE == 'oracle'\n ? 'varchar2'\n : DATABASE_TYPE == 'mssql'\n ? 'nvarchar'\n : 'varchar',\n enum:\n DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? DomainLinkType\n : undefined,\n length: DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb' ? undefined : 32,\n default: DomainLinkType.has\n })\n @Field({ description: 'The type of the relationship (e.g., has, maintains, owns).' })\n type: DomainLinkType\n\n /** Creation Timestamp */\n @CreateDateColumn()\n @Field({ description: 'The timestamp when the domain link was created.' })\n createdAt: Date\n\n /** Last Update Timestamp */\n @UpdateDateColumn()\n @Field({ description: 'The timestamp when the domain link was last updated.' })\n updatedAt: Date\n\n /** Creator User */\n @ManyToOne(() => User, { nullable: true })\n @Field(() => User, { nullable: true, description: 'The user who created the domain link.' })\n creator?: User\n\n @RelationId((domainLink: DomainLink) => domainLink.creator)\n creatorId?: string\n\n /** Updater User */\n @ManyToOne(() => User, { nullable: true })\n @Field(() => User, { nullable: true, description: 'The user who last updated the domain link.' })\n updater?: User\n\n @RelationId((domainLink: DomainLink) => domainLink.updater)\n updaterId?: string\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/domain-link/index.ts"],"names":[],"mappings":";;;AAAA,qDAA6C;AAC7C,iEAAwD;AACxD,uEAA8D;AAEjD,QAAA,QAAQ,GAAG,CAAC,2BAAU,CAAC,CAAA;AACvB,QAAA,SAAS,GAAG,CAAC,sCAAe,EAAE,4CAAkB,CAAC,CAAA;AACjD,QAAA,WAAW,GAAG,EAAE,CAAA","sourcesContent":["import { DomainLink } from './domain-link.js'\nimport { DomainLinkQuery } from './domain-link-query.js'\nimport { DomainLinkMutation } from './domain-link-mutation.js'\n\nexport const entities = [DomainLink]\nexport const resolvers = [DomainLinkQuery, DomainLinkMutation]\nexport const subscribers = []\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"domain-owner-mutation.js","sourceRoot":"","sources":["../../../server/service/domain-owner/domain-owner-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Resolver, Mutation, Arg, Ctx, Directive } from 'type-graphql'\nimport { Domain, getRepository } from '@things-factory/shell'\n\nimport { DomainOwner } from './domain-owner.js'\nimport { User } from '../user/user.js'\nimport { recordAuditAction } from '../audit/audit-recorder.js'\n\n@Resolver(of => DomainOwner)\nexport class DomainOwnerMutation {\n /**\n * 현재 도메인에 새 owner를 추가한다. 기존 도메인 오너 또는 수퍼유저만 호출 가능.\n *\n * 하위 호환: `Domain.owner` 캐시 필드가 비어 있으면 추가된 user를 세팅한다.\n */\n @Directive('@privilege(domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => DomainOwner, { description: 'Add a user as owner of the current domain.' })\n async addDomainOwner(\n @Arg('username') username: string,\n @Ctx() context: any,\n @Arg('reason', { nullable: true }) reason?: string\n ): Promise<DomainOwner> {\n const { domain, user: actor } = context.state\n\n return (getRepository(Domain) as any).manager.transaction(async (tx: any) => {\n const userRepo = tx.getRepository(User)\n const ownerRepo = tx.getRepository(DomainOwner)\n const domainRepo = tx.getRepository(Domain)\n\n // username 컬럼이 nullable — 사용자는 username 을 가지지 않고\n // email 만 갖는 경우가 많음. User.get username() 도 `username || email`\n // 을 리턴하므로 UI 가 email 을 보낼 수 있음. 둘 다 매칭한다.\n const targetUser = await userRepo\n .createQueryBuilder('u')\n .innerJoin('u.domains', 'd')\n .where('(u.username = :key OR u.email = :key) AND d.id = :domainId', {\n key: username,\n domainId: domain.id\n })\n .getOne()\n if (!targetUser) {\n throw new Error(`User '${username}' is not a member of this domain.`)\n }\n\n const existing = await ownerRepo.findOne({\n where: { domain: { id: domain.id }, user: { id: targetUser.id } }\n })\n if (existing) {\n throw new Error(`User '${username}' is already an owner of this domain.`)\n }\n\n const entry = ownerRepo.create({\n domain: { id: domain.id } as Domain,\n user: { id: targetUser.id } as User,\n grantedBy: actor,\n reason\n })\n const saved = await ownerRepo.save(entry)\n\n // 하위 호환 캐시: domain.owner가 비어 있으면 세팅\n if (!domain.owner) {\n await domainRepo.update(domain.id, { owner: targetUser.id })\n }\n\n // GraphQL 응답을 위해 relations 포함해 재조회.\n // (save() 반환값은 { user: {id}, grantedBy: actor } 인데 user/grantedBy 의\n // non-nullable 필드 email 등이 채워져 있지 않아 직렬화 에러 발생)\n return ownerRepo.findOneOrFail({\n where: { id: saved.id },\n relations: ['user', 'grantedBy', 'domain']\n })\n })\n }\n\n /**\n * 현재 도메인의 owner를 제거한다.\n * - 기존 도메인 오너 또는 수퍼유저만 호출 가능\n * - 마지막 남은 owner는 제거 불가 (최소 1명 유지)\n * - `Domain.owner` 캐시가 제거되는 user였다면, 남은 owner 중 하나로 재설정\n */\n @Directive('@privilege(domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Remove a user from the owners of the current domain.' })\n async removeDomainOwner(\n @Arg('username') username: string,\n @Ctx() context: any,\n @Arg('reason', { nullable: true }) _reason?: string\n ): Promise<boolean> {\n const { domain } = context.state\n\n return (getRepository(Domain) as any).manager.transaction(async (tx: any) => {\n const userRepo = tx.getRepository(User)\n const ownerRepo = tx.getRepository(DomainOwner)\n const domainRepo = tx.getRepository(Domain)\n\n // username 또는 email 둘 다 허용 — addDomainOwner 와 대칭.\n const targetUser = await userRepo.findOne({\n where: [{ username }, { email: username }]\n })\n if (!targetUser) {\n throw new Error(`User '${username}' not found.`)\n }\n\n const entry = await ownerRepo.findOne({\n where: { domain: { id: domain.id }, user: { id: targetUser.id } }\n })\n const hasLegacyOwner = domain.owner === targetUser.id\n\n if (!entry && !hasLegacyOwner) {\n throw new Error(`User '${username}' is not an owner of this domain.`)\n }\n\n // 마지막 1인 보호: DomainOwner 테이블 기준 count + legacy owner 포함 여부\n const ownerCount = await ownerRepo\n .createQueryBuilder('ow')\n .where('ow.domain_id = :d', { d: domain.id })\n .getCount()\n\n // 남을 owner 수 계산:\n // - DomainOwner 테이블에서 제거 대상이 있으면 ownerCount - 1\n // - legacy owner가 별도로 있고 DomainOwner에 없다면 +1\n let remaining = ownerCount\n if (entry) remaining -= 1\n // legacy owner가 지금 제거 대상과 다른 user라면, 그 user도 하나의 owner로 카운트\n if (domain.owner && domain.owner !== targetUser.id) {\n // legacy owner가 DomainOwner 테이블에도 이미 있는지\n const legacyInTable = await ownerRepo\n .createQueryBuilder('ow')\n .where('ow.domain_id = :d AND ow.user_id = :u', { d: domain.id, u: domain.owner })\n .getExists()\n if (!legacyInTable) remaining += 1\n }\n\n if (remaining < 1) {\n throw new Error(\n 'Cannot remove the last owner of a domain. Add another owner first.'\n )\n }\n\n if (entry) {\n await ownerRepo.delete(entry.id)\n }\n\n /* `delete()` passes no subscriber - the removal records itself, in the same transaction (ADR-0141 §4-1). */\n await recordAuditAction(\n { kind: 'domain.owner.remove', targetKind: 'User', targetIds: [targetUser.id], targetRole: 'handled' },\n { manager: tx, domainId: domain.id }\n )\n\n if (hasLegacyOwner) {\n // 캐시 재설정: 남은 DomainOwner 중 가장 먼저 추가된 사람\n const next = await ownerRepo\n .createQueryBuilder('ow')\n .where('ow.domain_id = :d', { d: domain.id })\n .orderBy('ow.grantedAt', 'ASC')\n .getOne()\n await domainRepo.update(domain.id, { owner: next?.userId ?? null })\n }\n\n return true\n })\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"domain-owner-query.js","sourceRoot":"","sources":["../../../server/service/domain-owner/domain-owner-query.ts"],"names":[],"mappings":";;;;AAAA,+CAAmE;AACnE,iDAA6D;AAE7D,uDAA+C;AAC/C,6CAAsC;AAG/B,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAC3B;;;OAGG;IAGG,AAAN,KAAK,CAAC,YAAY,CAAQ,OAAY;QACpC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAEhC,OAAO,IAAA,qBAAa,EAAC,6BAAW,CAAC;aAC9B,kBAAkB,CAAC,IAAI,CAAC;aACxB,iBAAiB,CAAC,SAAS,EAAE,MAAM,CAAC;aACpC,iBAAiB,CAAC,cAAc,EAAE,WAAW,CAAC;aAC9C,KAAK,CAAC,0BAA0B,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;aAC1D,OAAO,CAAC,cAAc,EAAE,KAAK,CAAC;aAC9B,OAAO,EAAE,CAAA;IACd,CAAC;IAED;;OAEG;IAGG,AAAN,KAAK,CAAC,aAAa,CACA,QAAgB,EAC1B,OAAY;QAEnB,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAEhC,6DAA6D;QAC7D,gBAAgB;QAChB,MAAM,IAAI,GAAG,MAAM,IAAA,qBAAa,EAAC,cAAI,CAAC,CAAC,OAAO,CAAC;YAC7C,KAAK,EAAE;gBACL,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE;gBACxC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE;aAChD;SACF,CAAC,CAAA;QACF,IAAI,CAAC,IAAI;YAAE,OAAO,KAAK,CAAA;QAEvB,4CAA4C;QAC5C,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,EAAE;YAAE,OAAO,IAAI,CAAA;QAEzC,MAAM,MAAM,GAAG,MAAM,IAAA,qBAAa,EAAC,6BAAW,CAAC;aAC5C,kBAAkB,CAAC,IAAI,CAAC;aACxB,KAAK,CAAC,uCAAuC,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;aAC5E,SAAS,EAAE,CAAA;QACd,OAAO,MAAM,CAAA;IACf,CAAC;CACF,CAAA;AAjDY,4CAAgB;AAOrB;IAFL,IAAA,wBAAS,EAAC,8DAA8D,CAAC;IACzE,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC,6BAAW,CAAC,EAAE,EAAE,WAAW,EAAE,oCAAoC,EAAE,CAAC;IACnE,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;oDAUxB;AAOK;IAFL,IAAA,wBAAS,EAAC,8DAA8D,CAAC;IACzE,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,oDAAoD,EAAE,CAAC;IAE9F,mBAAA,IAAA,kBAAG,EAAC,UAAU,CAAC,CAAA;IACf,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;qDAsBP;2BAhDU,gBAAgB;IAD5B,IAAA,uBAAQ,EAAC,EAAE,CAAC,EAAE,CAAC,6BAAW,CAAC;GACf,gBAAgB,CAiD5B","sourcesContent":["import { Resolver, Query, Arg, Ctx, Directive } from 'type-graphql'\nimport { Domain, getRepository } from '@things-factory/shell'\n\nimport { DomainOwner } from './domain-owner.js'\nimport { User } from '../user/user.js'\n\n@Resolver(of => DomainOwner)\nexport class DomainOwnerQuery {\n /**\n * 현재 도메인의 owner 목록 조회 — **도메인 오너 또는 수퍼유저만** 가능.\n * 오너 구성은 관리 정보라 비공개가 기본.\n */\n @Directive('@privilege(domainOwnerGranted: true, superUserGranted: true)')\n @Query(returns => [DomainOwner], { description: 'List owners of the current domain.' })\n async domainOwners(@Ctx() context: any): Promise<DomainOwner[]> {\n const { domain } = context.state\n\n return getRepository(DomainOwner)\n .createQueryBuilder('ow')\n .leftJoinAndSelect('ow.user', 'user')\n .leftJoinAndSelect('ow.grantedBy', 'grantedBy')\n .where('ow.domain_id = :domainId', { domainId: domain.id })\n .orderBy('ow.grantedAt', 'ASC')\n .getMany()\n }\n\n /**\n * 특정 user가 현재 도메인의 owner인지 확인 — 도메인 오너 또는 수퍼유저만.\n */\n @Directive('@privilege(domainOwnerGranted: true, superUserGranted: true)')\n @Query(returns => Boolean, { description: 'Check if a user is an owner of the current domain.' })\n async isDomainOwner(\n @Arg('username') username: string,\n @Ctx() context: any\n ): Promise<boolean> {\n const { domain } = context.state\n\n // username 또는 email 둘 다 허용 (username 컬럼이 nullable 이라 email 만\n // 세팅된 사용자도 있음).\n const user = await getRepository(User).findOne({\n where: [\n { username, domains: { id: domain.id } },\n { email: username, domains: { id: domain.id } }\n ]\n })\n if (!user) return false\n\n // Domain.owner 캐시 또는 DomainOwner 테이블 둘 다 확인\n if (domain.owner === user.id) return true\n\n const exists = await getRepository(DomainOwner)\n .createQueryBuilder('ow')\n .where('ow.domain_id = :d AND ow.user_id = :u', { d: domain.id, u: user.id })\n .getExists()\n return exists\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"domain-owner.js","sourceRoot":"","sources":["../../../server/service/domain-owner/domain-owner.ts"],"names":[],"mappings":";;;;AAAA,iDAA8C;AAC9C,qCASgB;AAChB,+CAAoD;AAEpD,6CAAsC;AAEtC;;;;;;;;;;;;;;;GAeG;AAII,IAAM,WAAW,GAAjB,MAAM,WAAW;CAmCvB,CAAA;AAnCY,kCAAW;AAGb;IAFR,IAAA,gCAAsB,EAAC,MAAM,CAAC;IAC9B,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAE,EAAE,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAC;;uCACtC;AAKnB;IAHC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IAClD,IAAA,oBAAU,GAAE;IACZ,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,EAAE,EAAE,WAAW,EAAE,4BAA4B,EAAE,CAAC;sCAC7D,cAAM;2CAAA;AAGd;IADC,IAAA,oBAAU,EAAC,CAAC,EAAe,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC;;6CAC3B;AAKhB;IAHC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAI,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IAChD,IAAA,oBAAU,GAAE;IACZ,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,cAAI,EAAE,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC;sCAC5D,cAAI;yCAAA;AAGV;IADC,IAAA,oBAAU,EAAC,CAAC,EAAe,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;;2CAC3B;AAId;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC3C,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,cAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,0CAA0C,EAAE,CAAC;sCACtF,cAAI;8CAAA;AAGf;IADC,IAAA,oBAAU,EAAC,CAAC,EAAe,EAAE,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC;;gDAC3B;AAInB;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,iCAAiC,EAAE,CAAC;sCAC/C,IAAI;8CAAA;AAIf;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,8CAA8C,EAAE,CAAC;;2CACzE;sBAlCH,WAAW;IAHvB,IAAA,gBAAM,GAAE;IACR,IAAA,eAAK,EAAC,wBAAwB,EAAE,CAAC,EAAe,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC5F,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,uEAAuE,EAAE,CAAC;GACxF,WAAW,CAmCvB","sourcesContent":["import { Domain } from '@things-factory/shell'\nimport {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n JoinColumn,\n ManyToOne,\n PrimaryGeneratedColumn,\n RelationId\n} from 'typeorm'\nimport { ObjectType, Field, ID } from 'type-graphql'\n\nimport { User } from '../user/user.js'\n\n/**\n * 도메인의 소유자(Owner)를 여러 명 허용하기 위한 join entity.\n *\n * 기존 `Domain.owner`(단일 UUID 문자열) 모델의 한계를 해소하고,\n * 여러 User를 같은 Domain의 owner로 등록 가능하게 한다. 모든 owner는 동등한\n * 권한을 가진다 (primary 개념 없음).\n *\n * `Domain.owner` 컬럼은 하위 호환을 위해 유지되며 \"대표 owner 표시용 캐시\"로\n * 활용된다:\n * - owner 추가 시, 기존 owner 컬럼이 비어있으면 자동 세팅\n * - owner 제거 시, 그 사람이 owner 컬럼이었다면 남은 owners 중 첫 사람으로 재설정\n * 권위 있는 소유권 정보는 이 테이블이 가지며, `domainOwnerGranted` 권한 체크는\n * 양쪽을 OR로 확인해 마이그레이션 기간 동안의 안전성을 보장한다.\n *\n * User 삭제 시 CASCADE로 소유권 엔트리 자동 해제.\n */\n@Entity()\n@Index('ix_domain_owner_unique', (ow: DomainOwner) => [ow.domain, ow.user], { unique: true })\n@ObjectType({ description: 'An ownership record binding a User to a Domain (multi-owner support).' })\nexport class DomainOwner {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier.' })\n readonly id: string\n\n @ManyToOne(type => Domain, { onDelete: 'CASCADE' })\n @JoinColumn()\n @Field(type => Domain, { description: 'Domain that the user owns.' })\n domain: Domain\n\n @RelationId((ow: DomainOwner) => ow.domain)\n domainId: string\n\n @ManyToOne(type => User, { onDelete: 'CASCADE' })\n @JoinColumn()\n @Field(type => User, { description: 'User who owns the domain.' })\n user: User\n\n @RelationId((ow: DomainOwner) => ow.user)\n userId: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'User who granted this ownership (audit).' })\n grantedBy: User\n\n @RelationId((ow: DomainOwner) => ow.grantedBy)\n grantedById: string\n\n @CreateDateColumn()\n @Field({ description: 'When the ownership was granted.' })\n grantedAt: Date\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Optional reason/memo for granting ownership.' })\n reason: string\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/domain-owner/index.ts"],"names":[],"mappings":";;;AAAA,uDAA+C;AAC/C,mEAA0D;AAC1D,yEAAgE;AAEnD,QAAA,QAAQ,GAAG,CAAC,6BAAW,CAAC,CAAA;AACxB,QAAA,SAAS,GAAG,CAAC,wCAAgB,EAAE,8CAAmB,CAAC,CAAA","sourcesContent":["import { DomainOwner } from './domain-owner.js'\nimport { DomainOwnerQuery } from './domain-owner-query.js'\nimport { DomainOwnerMutation } from './domain-owner-mutation.js'\n\nexport const entities = [DomainOwner]\nexport const resolvers = [DomainOwnerQuery, DomainOwnerMutation]\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"granted-role-mutation.js","sourceRoot":"","sources":["../../../server/service/granted-role/granted-role-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'\nimport { EntityManager, In, Not, Repository } from 'typeorm'\n\nimport { Domain, getRepository } from '@things-factory/shell'\n\nimport { Partner } from '../partner/partner.js'\nimport { Role } from '../role/role.js'\nimport { RolePatch } from '../role/role-types.js'\nimport { User } from '../user/user.js'\nimport { GrantedRole } from './granted-role.js'\n\n@Resolver(GrantedRole)\nexport class GrantedRoleMutation {\n @Directive('@privilege(category: \"partner\", privilege: \"mutation\")')\n @Directive('@transaction')\n @Mutation(returns => Boolean)\n async grantRoles(\n @Arg('customerId') customerId: string,\n @Arg('roles', type => [RolePatch]) roles: RolePatch[],\n @Ctx() context: ResolverContext\n ): Promise<Boolean> {\n const { tx, domain } = context.state\n // Check if current domain has partnership with passed `customer`\n const customerDomain: Domain = await tx.getRepository(Domain).findOneBy({ id: customerId })\n const customer: Partner = await tx.getRepository(Partner).findOne({\n where: { domain: { id: domain.id }, partnerDomain: { id: customerDomain.id } }\n })\n\n if (!customer) throw new Error(`Failed to find partnership with customer`)\n\n // Remove existing granted roles\n const grantedRoles: GrantedRole[] = await getGrantedRolesToCustomer(domain, customerDomain, tx)\n if (grantedRoles.length) {\n await tx.getRepository(GrantedRole).delete(grantedRoles.map((gr: GrantedRole) => gr.id))\n }\n\n // Insert newly granted roles\n await tx.getRepository(Role).findBy({\n id: In(roles.map((role: Partial<Role>) => role.id))\n })\n const newlyGrantedRoles: Partial<GrantedRole>[] = roles.map((role: Role) => {\n return {\n domain: customerDomain,\n role\n }\n })\n\n await tx.getRepository(GrantedRole).save(newlyGrantedRoles)\n\n // If there's someone having role which will be removed (refuse roles)\n // user roles should be removed as well\n const grantedRoleIds: string[] = roles.map((role: Partial<Role>) => role.id)\n const nonGrantedRoles: Role[] = await tx.getRepository(Role).find({\n where: { domain: { id: domain.id }, id: Not(In(grantedRoleIds)) }\n })\n\n if (nonGrantedRoles?.length) {\n // Find customer's user who has non granted roles already\n const nonGrantedRoleIds: string[] = nonGrantedRoles.map((role: Role) => role.id)\n\n let havingRefusedRoleCustomers: User[] = await getCustomerUsersByRoles(customerDomain, nonGrantedRoles, tx)\n havingRefusedRoleCustomers = havingRefusedRoleCustomers.map((customerUser: User) => {\n const customerDomains: Domain[] = customerUser.domains\n const customerDomainIds: string[] = customerDomains.map((domain: Domain) => domain.id)\n if (customerDomainIds.indexOf(domain.id) >= 0) {\n // Case for customer user is a member of current domain.\n // If user is a member of current domain user can have any roles of the domain even if the roles is not granted\n return customerUser\n } else {\n // Case for customer user is an user of partner domain.\n // An user of partner domain only can have granted roles\n customerUser.roles = customerUser.roles.filter((role: Role) => nonGrantedRoleIds.indexOf(role.id) < 0)\n return customerUser\n }\n })\n\n await tx.getRepository(User).save(havingRefusedRoleCustomers)\n }\n return true\n }\n}\n\nexport async function getGrantedCustomerUsers(\n domain: Domain,\n customerDomain: Domain,\n trx?: EntityManager\n): Promise<User[]> {\n const grantedRoles: GrantedRole[] = await getGrantedRolesToCustomer(domain, customerDomain, trx)\n const roles: Role[] = grantedRoles.map((grantedRole: GrantedRole) => grantedRole.role)\n return await getCustomerUsersByRoles(customerDomain, roles, trx)\n}\n\nexport async function getCustomerUsersByRoles(\n customerDomain: Domain,\n roles: Role[],\n trx?: EntityManager\n): Promise<User[]> {\n if (!roles.length) return []\n const userRepo: Repository<User> = trx?.getRepository(User) || getRepository(User)\n\n const customerUsers: User[] = await userRepo\n .createQueryBuilder('USER')\n .select('USER.id')\n .distinct(true)\n .leftJoin('USER.domains', 'U_DOMAIN')\n .leftJoin('USER.roles', 'U_ROLE')\n .where('U_DOMAIN.id = :customerDomainId', { customerDomainId: customerDomain.id })\n .groupBy('USER.id')\n .addGroupBy('U_ROLE.id')\n .having('U_ROLE.id IN (:...roleIds)', {\n roleIds: roles.map((role: Role) => role.id)\n })\n .getMany()\n\n return await userRepo.find({\n where: {\n id: In(customerUsers.map((user: User) => user.id))\n },\n relations: ['domains', 'roles', 'roles.domain']\n })\n}\n\nasync function getGrantedRolesToCustomer(\n domain: Domain,\n customerDomain: Domain,\n trx?: EntityManager\n): Promise<GrantedRole[]> {\n const grantedRoleRepo: Repository<GrantedRole> = trx?.getRepository(GrantedRole) || getRepository(GrantedRole)\n const grantedRoleQueryBuilder = grantedRoleRepo.createQueryBuilder('GRANTED_ROLE')\n return await grantedRoleQueryBuilder\n .leftJoinAndSelect('GRANTED_ROLE.domain', 'DOMAIN')\n .leftJoinAndSelect('GRANTED_ROLE.role', 'ROLE')\n .leftJoin('ROLE.domain', 'R_DOMAIN')\n .where('R_DOMAIN.id = :domainId', { domainId: domain.id })\n .andWhere('DOMAIN.id = :customerDomainId', { customerDomainId: customerDomain.id })\n .getMany()\n}\n\nexport async function terminateGrantedRoles(\n domain: Domain,\n customerDomain: Domain,\n trx?: EntityManager\n): Promise<void> {\n const userRepo: Repository<User> = trx?.getRepository(User) || getRepository(User)\n const grantedRoleRepo: Repository<GrantedRole> = trx?.getRepository(GrantedRole) || getRepository(GrantedRole)\n\n const grantedRoles: GrantedRole[] = await getGrantedRolesToCustomer(domain, customerDomain, trx)\n const customerUsers: User[] = await getGrantedCustomerUsers(domain, customerDomain, trx)\n\n for (let i: number = 0; i < customerUsers.length; i++) {\n customerUsers[i].roles = customerUsers[i].roles.filter((role: Role) => role.domain.id !== domain.id)\n }\n\n if (customerUsers?.length) await userRepo.save(customerUsers)\n if (grantedRoles?.length) await grantedRoleRepo.delete(grantedRoles.map((grantedRole: GrantedRole) => grantedRole.id))\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"granted-role-query.js","sourceRoot":"","sources":["../../../server/service/granted-role/granted-role-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Directive, FieldResolver, Query, Resolver, Root } from 'type-graphql'\nimport { SelectQueryBuilder } from 'typeorm'\n\nimport { Domain, getRepository } from '@things-factory/shell'\n\nimport { Partner } from '../partner/partner.js'\nimport { Role } from '../role/role.js'\nimport { GrantedRole } from './granted-role.js'\n\n@Resolver(GrantedRole)\nexport class GrantedRoleQuery {\n @Directive('@privilege(category: \"user\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(returns => [GrantedRole])\n async grantedRoles(@Ctx() context: ResolverContext): Promise<GrantedRole[]> {\n const { domain } = context.state\n return await getRepository(GrantedRole).find({\n where: { domain: { id: domain.id } }\n })\n }\n\n /**\n * @summary The role list that target customer being granted by domain.\n *\n * @param customerId\n * @param context\n * @returns\n */\n @Directive('@privilege(category: \"user\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [GrantedRole])\n async grantingRoles(@Arg('customerId') customerId: string, @Ctx() context: ResolverContext): Promise<GrantedRole[]> {\n const { domain } = context.state\n const customerDomain: Domain = await getRepository(Domain).findOneBy({ id: customerId })\n\n if (!customerDomain) throw new Error(`Failed to find customer by passed customerId (${customerId})`)\n\n const hasPartnership: boolean = Boolean(\n await getRepository(Partner).countBy({ domain: { id: domain.id }, partnerDomain: { id: customerDomain.id } })\n )\n\n if (!hasPartnership) throw new Error(`Company doesn't have partnership with ${customerDomain.name}`)\n\n const qb: SelectQueryBuilder<GrantedRole> = getRepository(GrantedRole)\n .createQueryBuilder('GRANTED_ROLE')\n .leftJoin('GRANTED_ROLE.role', 'ROLE')\n .where('GRANTED_ROLE.domain_id = :customerId', { customerId })\n .andWhere('ROLE.domain_id = :domainId ', { domainId: domain.id })\n\n return await qb.getMany()\n }\n\n @FieldResolver(type => Role)\n async role(@Root() grantedRole: GrantedRole): Promise<Role> {\n return await getRepository(Role).findOneBy({ id: grantedRole.roleId })\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() grantedRole: GrantedRole): Promise<Domain> {\n return await getRepository(Domain).findOneBy({ id: grantedRole.domainId })\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"granted-role.js","sourceRoot":"","sources":["../../../server/service/granted-role/granted-role.ts"],"names":[],"mappings":";;;;AAAA,iDAA8C;AAC9C,6CAAsC;AACtC,+CAAoD;AACpD,qCAAsF;AAK/E,IAAM,WAAW,GAAjB,MAAM,WAAW;CAkBvB,CAAA;AAlBY,kCAAW;AAGb;IAFR,IAAA,gCAAsB,EAAC,MAAM,CAAC;IAC9B,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAE,EAAE,EAAE,WAAW,EAAE,yCAAyC,EAAE,CAAC;;uCAC3D;AAInB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAI,CAAC;IACvB,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,yBAAyB,EAAE,CAAC;sCAC5C,cAAI;yCAAA;AAGV;IADC,IAAA,oBAAU,EAAC,CAAC,WAAwB,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC;;2CAC7C;AAId;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;IACzB,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,EAAE,EAAE,WAAW,EAAE,0CAA0C,EAAE,CAAC;sCAC1E,cAAM;2CAAA;AAGf;IADC,IAAA,oBAAU,EAAC,CAAC,WAAwB,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC;;6CAC7C;sBAjBL,WAAW;IAHvB,IAAA,gBAAM,GAAE;IACR,IAAA,eAAK,EAAC,mBAAmB,EAAE,CAAC,WAAwB,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAClH,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,yDAAyD,EAAE,CAAC;GAC1E,WAAW,CAkBvB","sourcesContent":["import { Domain } from '@things-factory/shell'\nimport { Role } from '../role/role.js'\nimport { ObjectType, Field, ID } from 'type-graphql'\nimport { Entity, ManyToOne, PrimaryGeneratedColumn, Index, RelationId } from 'typeorm'\n\n@Entity()\n@Index('ix_granted_role_0', (grantedRole: GrantedRole) => [grantedRole.role, grantedRole.domain], { unique: true })\n@ObjectType({ description: 'Represents a role that is granted to a specific domain.' })\nexport class GrantedRole {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier for the granted role.' })\n readonly id: string\n\n @ManyToOne(type => Role)\n @Field({ description: 'The role being granted.' })\n role: Role\n\n @RelationId((grantedRole: GrantedRole) => grantedRole.role)\n roleId: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { description: 'The domain to which the role is granted.' })\n domain?: Domain\n\n @RelationId((grantedRole: GrantedRole) => grantedRole.domain)\n domainId: string\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/granted-role/index.ts"],"names":[],"mappings":";;;AAAA,uDAA+C;AAC/C,mEAA0D;AAC1D,yEAAgE;AAEnD,QAAA,QAAQ,GAAG,CAAC,6BAAW,CAAC,CAAA;AACxB,QAAA,SAAS,GAAG,CAAC,wCAAgB,EAAE,8CAAmB,CAAC,CAAA","sourcesContent":["import { GrantedRole } from './granted-role.js'\nimport { GrantedRoleQuery } from './granted-role-query.js'\nimport { GrantedRoleMutation } from './granted-role-mutation.js'\n\nexport const entities = [GrantedRole]\nexport const resolvers = [GrantedRoleQuery, GrantedRoleMutation]\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"identity-confirmation.js","sourceRoot":"","sources":["../../../server/service/identity-confirmation/identity-confirmation.ts"],"names":[],"mappings":"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","sourcesContent":["import { GraphQLError } from 'graphql'\nimport gql from 'graphql-tag'\nimport jwt from 'jsonwebtoken'\n\nimport { config } from '@things-factory/env'\n\nimport { SECRET } from '../../utils/get-secret.js'\n\n/*\n * ── A recent confirmation that it is still the signed-in person (ADR-0168) ──────────────\n * A door whose facts must not open to whoever sits at an unattended desk says so with\n * `@recentConfirmation` beside its `@privilege`. The person confirms with their password or a\n * passkey; the confirmation is a signed cookie of its own, apart from the access token, that lives\n * ten minutes from the moment it was given - opening a door does not lengthen it (the user,\n * 2026-10-28). Every way to the door - a screen, an assistant tool - meets the same question there.\n */\n\nconst COOKIE = 'identity_confirmed'\nconst PURPOSE = 'identity-confirmation'\n\n/** The refusal's code - a screen that asks for the confirmation itself names it in `handledRefusals`. */\nexport const IDENTITY_CONFIRMATION_REFUSAL = 'identity-confirmation-required'\n\nexport const recentConfirmationDirectiveTypeDefs = gql`\n directive @recentConfirmation on FIELD_DEFINITION\n`\n\n/** How long a confirmation lives from the moment it was given, in minutes - 10 unless configured. */\nexport function confirmationMinutes(): number {\n const minutes = Number(config.get('identityConfirmation', {})?.minutes)\n return minutes > 0 ? minutes : 10\n}\n\nfunction cookieOptions(context, maxAge?: number) {\n return { secure: context.secure, httpOnly: true, sameSite: 'Lax' as const, ...(maxAge ? { maxAge } : {}) }\n}\n\n/** Remember that `userId` confirmed just now. */\nexport function rememberConfirmation(context, userId: string) {\n const minutes = confirmationMinutes()\n const token = jwt.sign({ sub: userId, purpose: PURPOSE }, SECRET, { expiresIn: minutes * 60 })\n\n context.cookies?.set(COOKIE, token, cookieOptions(context, minutes * 60 * 1000))\n}\n\n/**\n * Until when `userId`'s confirmation in this browser holds - null when there is none, it is another person's, or it\n * ran out. A screen reads it to put away what it shows the moment the confirmation ends.\n */\nexport function confirmedUntil(context, userId: string | undefined): Date | null {\n const token = context?.cookies?.get(COOKIE)\n if (!token || !userId) return null\n\n try {\n const payload = jwt.verify(token, SECRET) as { sub?: string; purpose?: string; exp?: number }\n return payload.purpose === PURPOSE && payload.sub === userId && payload.exp ? new Date(payload.exp * 1000) : null\n } catch {\n return null\n }\n}\n\n/** Whether `userId` confirmed within the last minutes - in this browser, as this person. */\nexport function isRecentlyConfirmed(context, userId: string | undefined): boolean {\n return confirmedUntil(context, userId) !== null\n}\n\nexport function forgetConfirmation(context) {\n context?.cookies?.set(COOKIE, '', cookieOptions(context))\n}\n\n/** The refusal of a door that asks for a recent confirmation, in the reader's words when there are some. */\nexport function confirmationRefusal(context): GraphQLError {\n const fallback = 'Confirm it is you to see this'\n let message = fallback\n try {\n const translated = typeof context?.t === 'function' ? context.t('error.identity confirmation required') : null\n if (translated && translated !== 'error.identity confirmation required') message = translated\n } catch {\n /* the refusal stands without its translation */\n }\n\n return new GraphQLError(message, {\n extensions: { code: 'IDENTITY_CONFIRMATION_REQUIRED', refusal: { code: IDENTITY_CONFIRMATION_REFUSAL, params: {} } }\n })\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/service/index.ts"],"names":[],"mappings":";;;;AAAA,mCAAmC;AACnC,wDAAkH;AAClH,8DAGwC;AACxC,uDAA+G;AAC/G,qDAAwE;AACxE,mDAAqG;AACrG,qDAA2G;AAC3G,0DAAkF;AAClF,sDAA2G;AAC3G,+CAIyB;AACzB,6DAAsE;AACtE,+FAAsG;AACtG,kDAA+F;AAC/F,2DAAiF;AACjF,oDAAqG;AACrG,+EAA2G;AAC3G,qDAA6C;AAC7C,+CAAsF;AACtF,wDAA6E;AAC7E,+CAAsF;AACtF,6DAAqF;AACrF,8DAA+H;AAC/H,sDAAwG;AACxG,uDAA4G;AAE5G,yBAAyB;AACzB,yFAA8D;AAC9D,2EAAgD;AAChD,uEAA4C;AAC5C,mEAAwC;AACxC,mEAAwC;AACxC,yDAA8B;AAC9B,wEAA6C;AAC7C,gHAAgH;AAChH,6EAAwG;AAA/F,2HAAA,iBAAiB,OAAA;AAAE,0HAAA,gBAAgB,OAAA;AAC5C,2FAA2F;AAC3F,6EAAuE;AAA9D,4HAAA,kBAAkB,OAAA;AAG3B,2EAAgD;AAChD,uEAA4C;AAC5C,iFAAsD;AACtD,yDAA8B;AAC9B,+DAAoC;AACpC,yEAA8C;AAC9C,uEAA4C;AAC5C,iFAAsD;AACtD,qFAA0D;AAC1D,mEAAwC;AACxC,kEAAuC;AACvC,yDAA0D;AAAjD,mHAAA,iBAAiB,OAAA;AAC1B,+DAAiH;AAAxG,sHAAA,iBAAiB,OAAA;AAAE,oHAAA,eAAe,OAAA;AAAE,+GAAA,UAAU,OAAA;AACvD,iEAAmF;AAA1E,uHAAA,iBAAiB,OAAA;AAAE,yHAAA,mBAAmB,OAAA;AAC/C,uDAAgH;AAAvG,kHAAA,iBAAiB,OAAA;AAAE,4GAAA,WAAW,OAAA;AAAE,2GAAA,UAAU,OAAA;AACnD,uFAA4D;AAC5D,uEAA4C;AAC5C,yEAA8C;AAC9C,6EAAkD;AAElD,kBAAkB;AAClB,6EAAkD;AAClD,yEAA8C;AAC9C,6EAAkD;AAClD,uFAA4D;AAC5D,qEAA0C;AAC1C,yEAA8C;AAC9C,+DAAoC;AACpC,+DAAoC;AACpC,6EAAkD;AAClD,mFAAwD;AAE3C,QAAA,QAAQ,GAAG;IACtB,cAAc;IACd,GAAG,mBAA0B;IAC7B,GAAG,mBAAoB;IACvB,GAAG,mBAAmB;IACtB,GAAG,mBAAiB;IACpB,GAAG,oBAAiB;IACpB,GAAG,oBAAY;IACf,GAAG,oBAAY;IACf,GAAG,oBAAe;IAClB,GAAG,mBAAmB;IACtB,GAAG,oBAAuB;IAC1B,GAAG,oBAAyB;IAC5B,GAAG,mBAAa;IAChB,GAAG,oBAAyB;IAC5B,GAAG,oBAAkB;IACrB,GAAG,oBAAmB;IACtB,GAAG,mBAAqB;CACzB,CAAA;AAED,8EAA8E;AACjE,QAAA,WAAW,GAAG,CAAC,GAAG,sBAAgB,CAAC,CAAA;AAEnC,QAAA,MAAM,GAAG;IACpB,QAAQ,EAAE;QACR,0BAA0B,EAA1B,mDAA0B;QAC1B,4BAA4B,EAA5B,8CAA4B;QAC5B,mCAAmC,EAAnC,8DAAmC;KACpC;IAED,6FAA6F;IAC7F,UAAU,EAAV,2BAAU;IAEV,eAAe,EAAE;QACf,sBAAsB;QACtB,GAAG,oBAA2B;QAC9B,GAAG,oBAAqB;QACxB,GAAG,oBAAoB;QACvB,GAAG,oBAAkB;QACrB,GAAG,qBAAkB;QACrB,GAAG,qBAAa;QAChB,GAAG,qBAAqB;QACxB,GAAG,qBAAa;QAChB,GAAG,qBAAgB;QACnB,GAAG,oBAAmB;QACtB,GAAG,oBAAkB;QACrB,GAAG,oBAAuB;QAC1B,GAAG,oBAAc;QACjB,GAAG,qBAAkB;QACrB,GAAG,qBAAoB;QACvB,GAAG,oBAAsB;QACzB,GAAG,qBAA0B;KAC9B;IACD,UAAU,EAAE;QACV,SAAS,EAAE,mDAA0B;KACtC;CACF,CAAA","sourcesContent":["/* IMPORT ENTITIES AND RESOLVERS */\nimport { entities as AccessRequestEntities, resolvers as AccessRequestResolvers } from './access-request/index.js'\nimport {\n entities as UsersAuthProvidersEntities,\n resolvers as UsersAuthProvidersResolvers\n} from './users-auth-providers/index.js'\nimport { entities as AuthProviderEntities, resolvers as AuthProviderResolvers } from './auth-provider/index.js'\nimport { resolvers as AppbindingResolver } from './app-binding/index.js'\nimport { entities as ApplianceEntities, resolvers as ApplianceResolvers } from './appliance/index.js'\nimport { entities as ApplicationEntities, resolvers as ApplicationResolvers } from './application/index.js'\nimport { resolvers as DomainGeneratorResolver } from './domain-generator/index.js'\nimport { entities as GrantedRoleEntities, resolvers as GrantedRoleResolver } from './granted-role/index.js'\nimport {\n entities as AuditEntities,\n resolvers as AuditResolvers,\n subscribers as AuditSubscribers\n} from './audit/index.js'\nimport { auditTargetDirectiveTypeDefs } from './audit/audit-target.js'\nimport { recentConfirmationDirectiveTypeDefs } from './identity-confirmation/identity-confirmation.js'\nimport { entities as PartnerEntities, resolvers as PartnerResolvers } from './partner/index.js'\nimport { entities as PasswordHistoryEntities } from './password-history/index.js'\nimport { entities as PrivilegeEntities, resolvers as PrivilegeResolvers } from './privilege/index.js'\nimport { privilegeDirectiveResolver, privilegeDirectiveTypeDefs } from './privilege/privilege-directive.js'\nimport { openFields } from './open-fields.js'\nimport { entities as RoleEntities, resolvers as RoleResolvers } from './role/index.js'\nimport { resolvers as RoleTemplateResolvers } from './role-template/index.js'\nimport { entities as UserEntities, resolvers as UserResolvers } from './user/index.js'\nimport { entities as VerificationTokenEntities } from './verification-token/index.js'\nimport { entities as WebAuthCredentialEntities, resolvers as WebAuthCredentialResolvers } from './web-auth-credential/index.js'\nimport { entities as DomainLinkEntities, resolvers as DomainLinkResolver } from './domain-link/index.js'\nimport { entities as DomainOwnerEntities, resolvers as DomainOwnerResolvers } from './domain-owner/index.js'\n\n/* EXPORT ENTITY TYPES */\nexport * from './users-auth-providers/users-auth-providers.js'\nexport * from './auth-provider/auth-provider.js'\nexport * from './application/application.js'\nexport * from './appliance/appliance.js'\nexport * from './privilege/privilege.js'\nexport * from './role/role.js'\nexport * from './privilege/privilege-axis.js'\n/* What a field asks for, by name — for another entrance to the same door (operato-twin ADR-0072 decision 5). */\nexport { declarePrivileges, privilegeOfField, type FieldGate } from './privilege/privilege-directive.js'\n/* Other entrances report AUTH's refusal without copying its cause or localized wording. */\nexport { privilegeRejection } from './privilege/privilege-rejection.js'\n/* How a module declares the fields it leaves open — see `privilege/open-field-rule.ts`. */\nexport { type OpenFieldsDeclaration } from './privilege/open-field-rule.js'\nexport * from './role-template/role-template.js'\nexport * from './role-template/role-task.js'\nexport * from './role-template/role-template-types.js'\nexport * from './user/user.js'\nexport * from './partner/partner.js'\nexport * from './granted-role/granted-role.js'\nexport * from './app-binding/app-binding.js'\nexport * from './password-history/password-history.js'\nexport * from './verification-token/verification-token.js'\nexport * from './audit/audit-request.js'\nexport * from './audit/audit-action.js'\nexport { registerAuditKind } from './audit/audit-kinds.js'\nexport { recordAuditAction, noteAuditAction, flushAudit, type AuditActionInput } from './audit/audit-recorder.js'\nexport { purgeExpiredAudit, startAuditRetention } from './audit/audit-retention.js'\nexport { registerWorkDoors, workOfField, workDoneBy, type WorkDoor, type WorkDone } from './audit/audit-work.js'\nexport * from './web-auth-credential/web-auth-credential.js'\nexport * from './domain-link/domain-link.js'\nexport * from './domain-owner/domain-owner.js'\nexport * from './access-request/access-request.js'\n\n/* EXPORT TYPES */\nexport * from './app-binding/app-binding-types.js'\nexport * from './appliance/appliance-types.js'\nexport * from './application/application-types.js'\nexport * from './domain-generator/domain-generator-types.js'\nexport * from './partner/partner-types.js'\nexport * from './privilege/privilege-types.js'\nexport * from './role/role-types.js'\nexport * from './user/user-types.js'\nexport * from './domain-link/domain-link-types.js'\nexport * from './access-request/access-request-types.js'\n\nexport const entities = [\n /* ENTITIES */\n ...UsersAuthProvidersEntities,\n ...AuthProviderEntities,\n ...ApplicationEntities,\n ...ApplianceEntities,\n ...PrivilegeEntities,\n ...RoleEntities,\n ...UserEntities,\n ...PartnerEntities,\n ...GrantedRoleEntities,\n ...PasswordHistoryEntities,\n ...VerificationTokenEntities,\n ...AuditEntities,\n ...WebAuthCredentialEntities,\n ...DomainLinkEntities,\n ...DomainOwnerEntities,\n ...AccessRequestEntities\n]\n\n/* The audit of who may do what, written where it is saved (ADR-0141 §3.3). */\nexport const subscribers = [...AuditSubscribers]\n\nexport const schema = {\n typeDefs: {\n privilegeDirectiveTypeDefs,\n auditTargetDirectiveTypeDefs,\n recentConfirmationDirectiveTypeDefs\n },\n\n /* The fields that carry no @privilege, and why — `open-fields.ts`, read by the directive. */\n openFields,\n\n resolverClasses: [\n /* RESOLVER CLASSES */\n ...UsersAuthProvidersResolvers,\n ...AuthProviderResolvers,\n ...ApplicationResolvers,\n ...ApplianceResolvers,\n ...PrivilegeResolvers,\n ...RoleResolvers,\n ...RoleTemplateResolvers,\n ...UserResolvers,\n ...PartnerResolvers,\n ...GrantedRoleResolver,\n ...AppbindingResolver,\n ...DomainGeneratorResolver,\n ...AuditResolvers,\n ...DomainLinkResolver,\n ...DomainOwnerResolvers,\n ...AccessRequestResolvers,\n ...WebAuthCredentialResolvers\n ],\n directives: {\n privilege: privilegeDirectiveResolver\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"open-fields.js","sourceRoot":"","sources":["../../server/service/open-fields.ts"],"names":[],"mappings":";;;AAEA;;;;;;GAMG;AACU,QAAA,UAAU,GAA0B;IAC/C,QAAQ,EAAE;QACR,sBAAsB,EAAE,4DAA4D;QACpF,eAAe,EAAE,wBAAwB;QACzC,oBAAoB,EAAE,0EAA0E;QAChG,4BAA4B,EAAE,sCAAsC;QACpE,8BAA8B,EAAE,2CAA2C;QAC3E,oBAAoB,EAClB,2JAA2J;QAC7J,yBAAyB,EAAE,qFAAqF;QAChH,wBAAwB,EAAE,kCAAkC;QAC5D,4BAA4B,EAAE,oFAAoF;QAClH,iCAAiC,EAAE,qFAAqF;QACxH,qBAAqB,EAAE,qHAAqH;QAC5I,wBAAwB,EACtB,6LAA6L;QAC/L,gCAAgC,EAAE,8DAA8D;QAChG,4BAA4B,EAAE,iDAAiD;QAC/E,oCAAoC,EAAE,oDAAoD;QAC1F,oCAAoC,EAAE,yGAAyG;KAChJ;CACF,CAAA","sourcesContent":["import type { OpenFieldsDeclaration } from './privilege/open-field-rule.js'\n\n/**\n * auth-base's root fields that declare no `@privilege` — every one of them, and why.\n *\n * There is no `notYetDeclared` here. The twelve that were open without a reason were closed on\n * 2026-09-20 (`c02ee9bdc1`); what is left answers about the caller, or about the installation\n * rather than anybody's data. An addition to this list needs its reason written first.\n */\nexport const openFields: OpenFieldsDeclaration = {\n byDesign: {\n 'Query.myAuditActions': \"the caller's own actions - the actor is the session's user\",\n 'Query.myRoles': \"the caller's own roles\",\n 'Query.hasPrivilege': 'whether the caller has one — a gate here would need the answer to itself',\n 'Query.domainsWithPrivilege': 'the domains where the caller has one',\n 'Query.checkUserBelongsDomain': 'whether the caller belongs to this domain',\n 'Query.passwordRule':\n \"the installation's password policy. The change-password screen needs it before the caller has any privilege — and after a forced reset they may have none\",\n 'Query.authProviderTypes': \"which provider types this build supports. A catalogue, not a tenant's configuration\",\n 'Query.myAccessRequests': \"the caller's own access requests\",\n 'Query.mayChangeParentRoles': \"whether the caller may give the parent domain's roles here - about the caller only\",\n 'Query.accessRequestDeciderCount': 'how many people an access request from the caller would reach - a number, never who',\n 'Query.tasksGranting': 'the tasks a refused person may ask for - the code catalog of work only, nothing of the domain (ADR-0103 decision 9)',\n 'Mutation.requestAccess':\n 'asked by someone refused for want of a role - a gate here would need the privilege being asked for. The door asks only for the caller and judges again that a role would open it (ADR-0103)',\n 'Mutation.withdrawAccessRequest': \"withdraws the caller's own pending request and nobody else's\",\n 'Query.myWebAuthCredentials': \"the caller's own passkeys (ADR-0156 decision 6)\",\n 'Mutation.updateMyWebAuthCredential': \"renames the caller's own passkey and nobody else's\",\n 'Mutation.deleteMyWebAuthCredential': \"removes the caller's own passkey and nobody else's - losing a device must not wait for an administrator\"\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/partner/index.ts"],"names":[],"mappings":";;;AAAA,6CAAsC;AACtC,yDAAiD;AACjD,+DAAuD;AAE1C,QAAA,QAAQ,GAAG,CAAC,oBAAO,CAAC,CAAA;AACpB,QAAA,SAAS,GAAG,CAAC,+BAAY,EAAE,qCAAe,CAAC,CAAA","sourcesContent":["import { Partner } from './partner.js'\nimport { PartnerQuery } from './partner-query.js'\nimport { PartnerMutation } from './partner-mutation.js'\n\nexport const entities = [Partner]\nexport const resolvers = [PartnerQuery, PartnerMutation]\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"partner-mutation.js","sourceRoot":"","sources":["../../../server/service/partner/partner-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'\n\nimport { Domain, getRepository } from '@things-factory/shell'\n\nimport { terminateGrantedRoles } from '../granted-role/granted-role-mutation.js'\nimport { Partner } from './partner.js'\n\n@Resolver(Partner)\nexport class PartnerMutation {\n @Directive('@privilege(category: \"partner\", privilege: \"mutation\")')\n @Mutation(returns => Boolean)\n async inviteCustomer(@Arg('customerDomainName') customerDomainName: string, @Ctx() context: ResolverContext) {\n // 1. Try to find existing customer\n const { domain, user } = context.state\n const customerDomain: Domain = await getRepository(Domain).findOne({ where: { name: customerDomainName } })\n if (!customerDomain) throw new Error(`There's no customer which has ${customerDomainName} as name`)\n\n const isExistingCustomer: boolean = Boolean(\n await getRepository(Partner).count({\n where: { domain: { id: domain.id }, partnerDomain: { id: customerDomain.id } }\n })\n )\n if (isExistingCustomer) throw new Error('Partner is registered as customer already')\n\n await getRepository(Partner).save({\n domain,\n partnerDomain: customerDomain,\n requester: user,\n approver: user\n })\n\n return true\n }\n\n @Directive('@privilege(category: \"partner\", privilege: \"mutation\")')\n @Directive('@transaction')\n @Mutation(returns => Boolean)\n async terminateContract(@Arg('partnerName') partnerName: string, @Ctx() context: ResolverContext) {\n const { tx, domain } = context.state\n\n // Find partnerDomain\n const partnerDomain: Domain = await tx.getRepository(Domain).findOne({\n where: { name: partnerName }\n })\n if (!partnerDomain) throw new Error(context.t('error.failed to find x', { x: context.t('label.partner') }))\n\n // Find partner\n const partner: Partner = await tx.getRepository(Partner).findOne({\n where: { domain: { id: domain.id }, partnerDomain: { id: partnerDomain.id } }\n })\n if (!partner) throw new Error(context.t('error.failed to find x', { x: context.t('label.partner') }))\n\n // Remove record from partner\n await tx.getRepository(Partner).delete(partner.id)\n\n // Remove granted roles\n await terminateGrantedRoles(domain, partnerDomain, tx)\n\n return true\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"partner-query.js","sourceRoot":"","sources":["../../../server/service/partner/partner-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Args, Ctx, Directive, FieldResolver, Query, Resolver, Root } from 'type-graphql'\nimport { SelectQueryBuilder } from 'typeorm'\n\nimport { Domain, DomainList, getRepository, ListParam, getQueryBuilderFromListParams, InheritedValueType } from '@things-factory/shell'\n\nimport { checkUserBelongsDomain } from '../../utils/check-user-belongs-domain.js'\nimport { User } from '../user/user.js'\nimport { Partner } from './partner.js'\nimport { PartnerList } from './partner-types.js'\n\n@Resolver(Partner)\nexport class PartnerQuery {\n @Directive('@privilege(category: \"partner\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => PartnerList)\n async partners(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<PartnerList> {\n if (await checkUserBelongsDomain(context.state.domain, context.state.user)) {\n const { domain } = context.state\n\n const queryBuilder = getQueryBuilderFromListParams({\n domain,\n // this domain's rows only - a parent domain's are another tenant's, whatever `inherited` the caller sent\n params: { ...params, inherited: InheritedValueType.None },\n repository: getRepository(Partner),\n alias: 'partner'\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n } else {\n throw new Error(`User doesn't belong in current domain`)\n }\n }\n\n @Directive('@privilege(category: \"partner\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [Domain])\n async customers(@Ctx() context: ResolverContext): Promise<Domain[]> {\n const { domain } = context.state\n const partners: Partner[] = await getRepository(Partner).find({\n where: { domain: { id: domain.id } },\n relations: ['partnerDomain']\n })\n\n return partners.map((p: Partner) => p.partnerDomain)\n }\n\n @Directive('@privilege(category: \"partner\", privilege: \"query\")')\n @Query(returns => DomainList)\n async searchCustomers(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<DomainList> {\n const { domain } = context.state\n const partners: Partner[] = await getRepository(Partner).find({\n where: { domain: { id: domain.id } },\n relations: ['partnerDomain']\n })\n\n const qb: SelectQueryBuilder<Domain> = await getQueryBuilderFromListParams({\n repository: getRepository(Domain),\n params,\n searchables: ['name', 'description']\n })\n\n qb.andWhereInIds(partners.map((p: Partner) => p.partnerDomain.id))\n const [items, total] = await qb.getManyAndCount()\n return { items, total }\n }\n\n @Directive('@privilege(category: \"partner\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [Domain])\n async vendors(@Ctx() context: ResolverContext): Promise<Domain[]> {\n const { domain } = context.state\n const qb: SelectQueryBuilder<Partner> = getRepository(Partner).createQueryBuilder('PARTNER')\n const partners: Partner[] = await qb\n .leftJoinAndSelect('PARTNER.domain', 'DOMAIN')\n .leftJoinAndSelect('PARTNER.partnerDomain', 'P_DOMAIN')\n .where('P_DOMAIN.id = :domainId', { domainId: domain.id })\n .getMany()\n\n return partners.map((p: Partner) => p.domain)\n }\n\n @FieldResolver()\n async domain(@Root() partner: Partner) {\n return await getRepository(Domain).findOneBy({ id: partner.domainId })\n }\n\n @FieldResolver()\n async partnerDomain(@Root() partner: Partner) {\n return await getRepository(Domain).findOneBy({ id: partner.partnerDomainId })\n }\n\n @FieldResolver()\n async requester(@Root() partner: Partner) {\n return await getRepository(User).findOneBy({ id: partner.requesterId })\n }\n\n @FieldResolver()\n async approver(@Root() partner: Partner) {\n return await getRepository(User).findOneBy({ id: partner.approverId })\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"partner-types.js","sourceRoot":"","sources":["../../../server/service/partner/partner-types.ts"],"names":[],"mappings":";;;;AAAA,+CAAqD;AACrD,6CAAsC;AAG/B,IAAM,WAAW,GAAjB,MAAM,WAAW;CAMvB,CAAA;AANY,kCAAW;AAEtB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,oBAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,gCAAgC,EAAE,CAAC;;0CAC5E;AAGhB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,mCAAmC,EAAE,CAAC;;0CAC5E;sBALF,WAAW;IADvB,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,mCAAmC,EAAE,CAAC;GACpD,WAAW,CAMvB","sourcesContent":["import { Field, Int, ObjectType } from 'type-graphql'\nimport { Partner } from './partner.js'\n\n@ObjectType({ description: 'A paginated list of partnerships.' })\nexport class PartnerList {\n @Field(type => [Partner], { nullable: true, description: 'The list of partnership items.' })\n items: Partner[]\n\n @Field(type => Int, { nullable: true, description: 'The total number of partnerships.' })\n total: number\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"partner.js","sourceRoot":"","sources":["../../../server/service/partner/partner.ts"],"names":[],"mappings":";;;;AAAA,iDAA8C;AAC9C,qCAQgB;AAChB,+CAAoD;AACpD,6CAAsC;AAK/B,IAAM,OAAO,GAAb,MAAM,OAAO;CAwCnB,CAAA;AAxCY,0BAAO;AAGT;IAFR,IAAA,gCAAsB,EAAC,MAAM,CAAC;IAC9B,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAE,EAAE,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;;mCAC1D;AAInB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;IACzB,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,EAAE,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;sCACxE,cAAM;uCAAA;AAGf;IADC,IAAA,oBAAU,EAAC,CAAC,OAAgB,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;;yCACjC;AAIhB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;IACzB,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,EAAE,EAAE,WAAW,EAAE,kCAAkC,EAAE,CAAC;sCAC3D,cAAM;8CAAA;AAGtB;IADC,IAAA,oBAAU,EAAC,CAAC,OAAgB,EAAE,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC;;gDACjC;AAIvB;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,mDAAmD,EAAE,CAAC;sCAC/E,IAAI;4CAAA;AAIjB;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,kDAAkD,EAAE,CAAC;sCAC/E,IAAI;2CAAA;AAIhB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC3C,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,yCAAyC,EAAE,CAAC;sCACvE,cAAI;0CAAA;AAGf;IADC,IAAA,oBAAU,EAAC,CAAC,OAAgB,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC;;4CACjC;AAInB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC3C,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;sCACvE,cAAI;yCAAA;AAGd;IADC,IAAA,oBAAU,EAAC,CAAC,OAAgB,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;;2CACjC;kBAvCP,OAAO;IAHnB,IAAA,gBAAM,GAAE;IACR,IAAA,eAAK,EAAC,cAAc,EAAE,CAAC,OAAgB,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACtG,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,+CAA+C,EAAE,CAAC;GAChE,OAAO,CAwCnB","sourcesContent":["import { Domain } from '@things-factory/shell'\nimport {\n CreateDateColumn,\n Entity,\n Index,\n ManyToOne,\n PrimaryGeneratedColumn,\n UpdateDateColumn,\n RelationId\n} from 'typeorm'\nimport { ObjectType, Field, ID } from 'type-graphql'\nimport { User } from '../user/user.js'\n\n@Entity()\n@Index('ix_partner_0', (partner: Partner) => [partner.domain, partner.partnerDomain], { unique: true })\n@ObjectType({ description: 'Represents a partnership between two domains.' })\nexport class Partner {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier for the partnership.' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { description: 'The domain initiating the partnership.' })\n domain?: Domain\n\n @RelationId((partner: Partner) => partner.domain)\n domainId: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { description: 'The domain being partnered with.' })\n partnerDomain?: Domain\n\n @RelationId((partner: Partner) => partner.partnerDomain)\n partnerDomainId: string\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'The timestamp when the partnership was requested.' })\n requestedAt: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'The timestamp when the partnership was approved.' })\n approvedAt: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field({ nullable: true, description: 'The user who requested the partnership.' })\n requester: User\n\n @RelationId((partner: Partner) => partner.requester)\n requesterId: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field({ nullable: true, description: 'The user who approved the partnership.' })\n approver: User\n\n @RelationId((partner: Partner) => partner.approver)\n approverId: string\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/password-history/index.ts"],"names":[],"mappings":";;;AAAA,+DAAuD;AAE1C,QAAA,QAAQ,GAAG,CAAC,qCAAe,CAAC,CAAA","sourcesContent":["import { PasswordHistory } from './password-history.js'\n\nexport const entities = [PasswordHistory]\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"password-history.js","sourceRoot":"","sources":["../../../server/service/password-history/password-history.ts"],"names":[],"mappings":";;;;AAAA,qCAAuD;AACvD,+CAAoD;AAI7C,IAAM,eAAe,GAArB,MAAM,eAAe;CAU3B,CAAA;AAVY,0CAAe;AAG1B;IAFC,IAAA,uBAAa,GAAE;IACf,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAE,EAAE,EAAE,WAAW,EAAE,2DAA2D,EAAE,CAAC;;+CAClF;AAMd;IAJC,IAAA,gBAAM,EAAC;QACN,QAAQ,EAAE,IAAI;KACf,CAAC;IACD,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,4CAA4C,EAAE,CAAC;;gDACtE;0BATJ,eAAe;IAF3B,IAAA,gBAAM,GAAE;IACR,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,oDAAoD,EAAE,CAAC;GACrE,eAAe,CAU3B","sourcesContent":["import { Entity, Column, PrimaryColumn } from 'typeorm'\nimport { ObjectType, Field, ID } from 'type-graphql'\n\n@Entity()\n@ObjectType({ description: \"Stores a user's password history to prevent reuse.\" })\nexport class PasswordHistory {\n @PrimaryColumn()\n @Field(type => ID, { description: 'The ID of the user associated with this password history.' })\n userId: string\n\n @Column({\n nullable: true\n })\n @Field({ nullable: true, description: 'A serialized list of past password hashes.' })\n history: string\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/privilege/index.ts"],"names":[],"mappings":";;;AAAA,iDAA0C;AAC1C,6DAAqD;AACrD,mEAA2D;AAE9C,QAAA,QAAQ,GAAG,CAAC,wBAAS,CAAC,CAAA;AACtB,QAAA,SAAS,GAAG,CAAC,mCAAc,EAAE,yCAAiB,CAAC,CAAA","sourcesContent":["import { Privilege } from './privilege.js'\nimport { PrivilegeQuery } from './privilege-query.js'\nimport { PrivilegeMutation } from './privilege-mutation.js'\n\nexport const entities = [Privilege]\nexport const resolvers = [PrivilegeQuery, PrivilegeMutation]\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"open-field-rule.js","sourceRoot":"","sources":["../../../server/service/privilege/open-field-rule.ts"],"names":[],"mappings":"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","sourcesContent":["import { getMetadataStorage } from 'type-graphql'\n\nimport { loader, orderedModuleNames } from '@things-factory/env'\n\n/**\n * Which root fields are allowed to carry no `@privilege`, module by module\n * (`docs/design/auth-rebuild.md` §6-2 and §8 step 1; the question sheet of 2026-09-24, Q1 · Q2).\n *\n * ── The problem this answers ────────────────────────────────────────────────\n * `@privilege` is opt-in. A root field that declares nothing is open to anyone in the domain,\n * and it is recorded as open in exactly the way a field somebody chose to open is — no error, no\n * warning, nothing to grep for. On 2026-09-24 each product served about 300 of them, and new ones\n * kept arriving the same way; `deleteAppBinding`, which deleted any account in the installation,\n * went in like that.\n *\n * ── The declaration ─────────────────────────────────────────────────────────\n * A module states its undeclared fields on the `schema` object it already exports, beside its\n * `resolverClasses`, in two lists that mean different things:\n *\n * byDesign open on purpose, with the reason. `myRoles` answers about the caller;\n * `passwordRule` has to answer before the caller has any privilege at all.\n * These do not shrink.\n * notYetDeclared open because nobody has decided what they guard yet. Names only. This list\n * is meant to reach zero, and when it does the key goes with it.\n *\n * Mixing the two would turn the transition list into a permanent allow-list.\n *\n * ── Why a module opts in, rather than every field at once ───────────────────\n * The four products each serve resolvers of their own from another repository. Enforcing on every\n * field the day this lands would stop all four from booting in development. So a module that\n * declares `openFields` is held to it, and one that does not is left as it was — and counted\n * (`tests/open-fields-framework.test.ts`), so that \"not opted in\" is visible rather than silent.\n *\n * ── Why the data sits on `schema` and not behind a call into auth-base ──────\n * `shell` has resolvers and cannot depend on auth-base (auth-base depends on it), and five other\n * modules with resolvers do not depend on it either. The `schema` object every module already\n * exports needs no import, and it is what the server walks to build the schema in the first place.\n */\n\n/** What a module says about its undeclared root fields. Keys are `Type.field`, e.g. `Query.myRoles`. */\nexport type OpenFieldsDeclaration = {\n byDesign?: Record<string, string>\n notYetDeclared?: string[]\n}\n\n/** A module as the server sees it: a name, and the `schema` object its server entry exports. */\nexport type DeclaringModule = {\n name: string\n schema?: {\n resolverClasses?: Function[]\n openFields?: OpenFieldsDeclaration\n } | null\n}\n\n/** For one root field of an opted-in module: which module, and which list names it (if any). */\nexport type Covered = {\n module: string\n listed: 'by-design' | 'not-yet-declared' | null\n}\n\nexport type Coverage = Map<string, Covered>\n\n/**\n * The modules the running server loaded, in the order it loaded them.\n *\n * Under a test runner `orderedModuleNames` is empty, so this answers nothing and no field is\n * enforced — a test that wants enforcement passes its modules explicitly. A module whose entry\n * cannot be loaded here is skipped: the server itself would have failed on it before this point.\n */\nexport function modulesFromLoader(): DeclaringModule[] {\n return (orderedModuleNames || []).map((name: string) => {\n try {\n return { name, schema: loader(name)?.schema }\n } catch (e) {\n return { name, schema: null }\n }\n })\n}\n\nconst ROOTS = [\n ['Query', 'queries'],\n ['Mutation', 'mutations'],\n ['Subscription', 'subscriptions']\n] as const\n\n/**\n * The root fields each opted-in module's own resolver classes make, and what that module's lists\n * say about each.\n *\n * Attribution comes from type-graphql's metadata — the same record `buildSchema` reads — so a\n * field belongs to the module whose class declared it, not to whichever module happens to be\n * built alongside it.\n */\nexport function coverageOf(modules: DeclaringModule[]): Coverage {\n const storage = getMetadataStorage() as any\n const coverage: Coverage = new Map()\n\n for (const module of modules) {\n const declaration = module.schema?.openFields\n\n if (!declaration) {\n continue\n }\n\n const classes = new Set(module.schema?.resolverClasses || [])\n const byDesign = declaration.byDesign || {}\n const notYet = new Set(declaration.notYetDeclared || [])\n\n for (const [typeName, bucket] of ROOTS) {\n for (const field of storage[bucket] || []) {\n if (!classes.has(field.target)) {\n continue\n }\n\n const where = `${typeName}.${field.schemaName}`\n\n coverage.set(where, {\n module: module.name,\n listed: where in byDesign ? 'by-design' : notYet.has(where) ? 'not-yet-declared' : null\n })\n }\n }\n }\n\n return coverage\n}\n\n/**\n * What to do with a root field that carries no `@privilege`.\n *\n * open-by-design leave it open — its module says why\n * open-not-yet-declared leave it open — its module has it on the list to close\n * unlisted its module opted in and says nothing about it: this is the field\n * that arrived quietly, and the one this exists to stop\n * not-opted-in its module has not declared lists; unchanged from before\n */\nexport type UndeclaredVerdict = 'open-by-design' | 'open-not-yet-declared' | 'unlisted' | 'not-opted-in'\n\nexport function judgeUndeclared(where: string, coverage: Coverage): UndeclaredVerdict {\n const covered = coverage.get(where)\n\n if (!covered) {\n return 'not-opted-in'\n }\n\n if (covered.listed === 'by-design') {\n return 'open-by-design'\n }\n\n if (covered.listed === 'not-yet-declared') {\n return 'open-not-yet-declared'\n }\n\n return 'unlisted'\n}\n\n/**\n * Where an unlisted field is stopped (question sheet Q2).\n *\n * boot the schema refuses to build and names every such field at once. Development and\n * tests, so the person who added it sees it on their own screen before it ships\n * request the server builds, and that one field refuses every call and logs its name.\n * Production, so a line somebody forgot costs one field and not the whole product\n *\n * Neither ever opens anything. Wrong in the worst case means one field refuses.\n */\nexport type EnforcementMode = 'boot' | 'request'\n\nexport function enforcementMode(): EnforcementMode {\n return process.env.NODE_ENV === 'production' ? 'request' : 'boot'\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"privilege-axis.js","sourceRoot":"","sources":["../../../server/service/privilege/privilege-axis.ts"],"names":[],"mappings":"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","sourcesContent":["import { logger } from '@things-factory/env'\n\n/**\n * The axis vocabulary this installation uses.\n *\n * ── ⚠ Call `declareAxes` at the top of the module's `server/index.ts` ────────\n * Not from a bootstrap hook. The check runs while the schema is assembled, and the schema is\n * assembled before every hook a module can reach:\n *\n * shell/server/server.ts:115 emitHook('bootstrap-module-subscription')\n * shell/server/server.ts:117 await schema() ← the axis check runs in here\n * shell/server/server.ts:295 emitHook('bootstrap-module-start')\n *\n * `bootstrap-module-start` is where a module registers most things, role templates included,\n * and it is 178 lines too late for this one.\n *\n * ── What an axis is ──────────────────────────────────────────────────────────\n * The `privilege:` half of `@privilege(category:, privilege:)`. It does **not** name a\n * GraphQL operation. It names which of a category's gates a role has to hold, and the values\n * this house uses happen to borrow transport words.\n *\n * ── Why the framework does not own the list ──────────────────────────────────\n * Closing the axis to `query | mutation` was ruled and then withdrawn (architect,\n * 2026-09-15). It was measured first:\n *\n * things-factory + operato-application 792 declarations, all query or mutation\n * dssp 65 declarations, 40 of them neither\n * kpi: read · input · assessment · sentiment\n * finalize · recalculate · auto-collect\n * basic-info\n *\n * A framework enum would have made dssp's upgrade a 40-declaration migration, and the cost\n * would fall on people who were not in the room. The framework cannot know which words are\n * right; it does not own the modules that use them.\n *\n * ── What this buys ───────────────────────────────────────────────────────────\n * A typo stops being a silent gate. `@privilege(category: \"board\", privilege: \"mutaiton\")`\n * used to register a pair in `process['PRIVILEGES']` that nobody would ever be granted — a\n * door permanently shut, with no error anywhere.\n */\n\nconst REGISTRY = 'PRIVILEGE_AXES'\n\n/**\n * What an installation gets when no module says otherwise.\n *\n * The two travel together: a house running on the default vocabulary is also running on the\n * default answer to \"which of these is read-only\". Splitting them would leave the common case\n * — nobody declared anything — with a vocabulary and no idea which half is safe.\n */\nexport const DEFAULT_AXES = ['query', 'mutation']\nexport const DEFAULT_READ_ONLY_AXES = ['query']\n\ntype Registry = { axes: Set<string>; readOnly: Set<string>; declared: boolean }\n\nfunction registry(): Registry {\n if (!process[REGISTRY]) {\n process[REGISTRY] = { axes: new Set<string>(), readOnly: new Set<string>(), declared: false }\n }\n\n return process[REGISTRY]\n}\n\n/**\n * Declare the axes a module uses, and which of them are read-only. Additive.\n *\n * Additive rather than one installation-wide list because a single installation genuinely\n * mixes vocabularies: in dssp, `project` is declared with query/mutation while `kpi` uses\n * eight words of its own. Each module says what it uses, and says it in the same call that\n * says which are read-only — a separate call for the second half could drift out of step with\n * the first, and drift like that is silent.\n *\n * Declaring an axis that is already known is not an error. Two modules reaching for `read`\n * independently is the case this is built for, not a conflict.\n *\n * ── `readOnly` means \"holding only this axis changes nothing\" ────────────────\n * It does **not** mean `@Query`. The two come apart, and where they do the axis is right and\n * the operation type is the loose one:\n *\n * @Mutation(returns => ExportResult)\n * @Directive('@privilege(category: \"label-studio\", privilege: \"query\")')\n * async exportLabelStudioAnnotations(…)\n *\n * That calls an external API's export and hands back what it returns. Nothing in our database\n * moves. It is declared `@Mutation` and the axis is `query`, and **the axis is the correct\n * one** — a role holding only `label-studio:query` still changes nothing by running it.\n *\n * Six declarations in this house disagree this way, and all six are deliberate. Do not\n * \"fix\" them to match their operation type.\n */\nexport function declareAxes(axes: string[], options: { readOnly?: string[] } = {}): void {\n if (!Array.isArray(axes) || axes.length === 0) {\n throw new Error(\n 'declareAxes needs at least one axis. An empty list would refuse every declaration in ' +\n 'the installation, which is never what the caller meant.'\n )\n }\n\n for (const axis of axes) {\n if (typeof axis !== 'string' || !axis.trim()) {\n throw new Error(`declareAxes got ${JSON.stringify(axis)} as an axis. Axes are non-empty strings.`)\n }\n }\n\n const readOnly = options.readOnly || []\n\n /*\n * A read-only axis has to be one of the axes named in the same call.\n *\n * Otherwise a typo here is the quietest kind: `readOnly: ['querry']` would mark nothing,\n * VIEWER would silently lose every category of this module, and the screen would count the\n * shortfall correctly and show it as fact.\n */\n for (const axis of readOnly) {\n if (!axes.includes(axis)) {\n throw new Error(\n `declareAxes was told \"${axis}\" is read-only, but that axis is not in the same call. ` +\n `Declared here: ${axes.join(', ')}.`\n )\n }\n }\n\n const store = registry()\n\n for (const axis of axes) {\n store.axes.add(axis)\n }\n\n for (const axis of readOnly) {\n store.readOnly.add(axis)\n }\n\n store.declared = true\n}\n\n/**\n * The axes this installation accepts.\n *\n * Falls back to the default rather than to \"no check\": an empty registry means nobody\n * declared, not that everything is allowed.\n */\nexport function declaredAxes(): Set<string> {\n const store = registry()\n\n return store.declared ? store.axes : new Set(DEFAULT_AXES)\n}\n\n/** Whether a value may be used as an axis here. */\nexport function isDeclaredAxis(axis: string): boolean {\n return declaredAxes().has(axis)\n}\n\n/**\n * The axes that open nothing a role can change.\n *\n * Empty is a real answer, and it is different from the default. A house that declared its own\n * vocabulary and never said which half is read-only has not told us — see\n * `readOnlyAxesAreKnown`.\n */\nexport function readOnlyAxes(): Set<string> {\n const store = registry()\n\n return store.declared ? store.readOnly : new Set(DEFAULT_READ_ONLY_AXES)\n}\n\n/**\n * Whether anyone has said which axes are read-only.\n *\n * `computedRoleTemplates` asks this before offering VIEWER. Guessing would mean matching the\n * literal word `query`, which is what this replaces: it is right in this house and wrong in\n * dssp, where the read axis is spelled `read`.\n */\nexport function readOnlyAxesAreKnown(): boolean {\n return readOnlyAxes().size > 0\n}\n\n/**\n * Say what the vocabulary ended up being.\n *\n * The list is not in the SDL and cannot be, since it differs per installation. A line at boot\n * is the honest substitute — and it is the only way to tell \"nobody declared, so these are the\n * defaults\" from \"someone declared exactly these\".\n */\nexport function reportDeclaredAxes(): void {\n const store = registry()\n const axes = [...declaredAxes()].sort().join(', ')\n const readOnly = [...readOnlyAxes()].sort().join(', ')\n\n if (!store.declared) {\n logger.info(`[privilege] no module declared privilege axes; using the defaults: ${axes} (read-only: ${readOnly})`)\n return\n }\n\n logger.info(`[privilege] axes declared by this installation: ${axes}`)\n\n if (readOnlyAxesAreKnown()) {\n logger.info(`[privilege] read-only axes: ${readOnly}`)\n return\n }\n\n /*\n * Loud, because the consequence is a template quietly going missing from the role screen.\n * \"We do not know\" is not \"there are none\", and folding the two would hand an administrator\n * a VIEWER that opens nothing.\n */\n logger.warn(\n '[privilege] no module said which axes are read-only, so the VIEWER template is not offered. ' +\n \"Add it where the axes are declared: declareAxes([...], { readOnly: ['query'] }).\"\n )\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"privilege-deprecation.js","sourceRoot":"","sources":["../../../server/service/privilege/privilege-deprecation.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG;;;AAcH,sDAqBC;AA9BD,2DAA2D;AACpD,MAAM,cAAc,GAAG,CAAC,QAAgB,EAAE,SAAiB,EAAE,EAAE,CAAC,GAAG,QAAQ,IAAI,SAAS,EAAE,CAAA;AAApF,QAAA,cAAc,kBAAsE;AAEjG;;;;;GAKG;AACH,SAAgB,qBAAqB,CACnC,QAA+C,EAC/C,GAAyC;IAEzC,MAAM,YAAY,GAAG,QAAQ,IAAI,EAAE,CAAA;IAEnC;;;;OAIG;IACH,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAA;IACd,CAAC;IAED,uDAAuD;IACvD,IAAI,CAAC,GAAG,EAAE,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QACjC,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,CAAC,CAAC,IAAA,sBAAc,EAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,CAAA;AAClE,CAAC","sourcesContent":["/*\n * 유령 권한 판정 — **이 배포의 어떤 코드도 더 이상 요구하지 않는 권한인가.** 순수.\n *\n * ── 왜 있나 ─────────────────────────────────────────────────────────────────\n * 권한 마스터는 `@privilege` 지시자가 정의하고, 부팅 때 없는 행만 만든다(`auth-base/server/index.ts`).\n * 그 동기화는 **추가만** 한다 — 지시자가 사라져도 행은 남는다. 그래서 관리자는 역할에 붙일 수 있고\n * 붙여도 아무 일이 없는 권한을 목록에서 보게 된다. (실제로 트윈에서 조회 게이트 둘을 걷어낸 뒤\n * `twin/query` 행이 남았다.)\n *\n * ── 왜 지우지 않고 표시하나 ─────────────────────────────────────────────────\n * 역할이 이미 그 권한을 참조하고 있을 수 있고, 행을 지우면 **누구에게 무엇을 줬는지의 기록까지**\n * 사라진다. 관리자가 보고 떼는 것이 옳다.\n *\n * ── 왜 저장하지 않고 계산하나 ───────────────────────────────────────────────\n * ① 컬럼 추가와 마이그레이션이 필요 없다(멀티DB 5종).\n * ② 한 DB 를 모듈 구성이 다른 앱 둘이 함께 볼 때, 저장했다면 부팅마다 서로 값을 뒤집는다.\n *\n * 그래서 뜻은 \"영원히 죽었다\" 가 아니라 **\"지금 이 배포가 요구하지 않는다\"** 다.\n */\n\n/** `process['PRIVILEGES']` 의 모양 — 키는 `\"<category> <privilege>\"`. */\nexport type DeclaredPrivileges = Record<string, unknown>\n\n/** 지시자가 만드는 키. 저장된 행의 `name` 이 지시자의 `privilege` 에 해당한다. */\nexport const declarationKey = (category: string, privilege: string) => `${category} ${privilege}`\n\n/**\n * 저장된 권한 행이 유령인가.\n *\n * @param declared 지시자들이 선언한 권한(`process['PRIVILEGES']`).\n * @param row 저장된 행(`category` + `name`).\n */\nexport function isDeprecatedPrivilege(\n declared: DeclaredPrivileges | undefined | null,\n row: { category?: string; name?: string }\n): boolean {\n const declarations = declared ?? {}\n\n /*\n * 선언이 하나도 없으면 **판단하지 않는다.** 스키마가 아직 구성되지 않은 상황에서 전부 \"유령\" 이라고\n * 답하면 있지도 않은 문제를 만든다. 지금은 스키마 구성이 listen 보다 먼저 끝나므로 실제로는 비지\n * 않지만, 거짓 경보보다 무판단이 정직하다.\n */\n if (Object.keys(declarations).length === 0) {\n return false\n }\n\n /* 행이 반쪽이면(둘 중 하나가 없으면) 어떤 선언과도 짝지을 수 없다 — 그것은 유령이다. */\n if (!row?.category || !row?.name) {\n return true\n }\n\n return !(declarationKey(row.category, row.name) in declarations)\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"privilege-directive.js","sourceRoot":"","sources":["../../../server/service/privilege/privilege-directive.ts"],"names":[],"mappings":"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","sourcesContent":["import { defaultFieldResolver, GraphQLError, GraphQLSchema } from 'graphql'\nimport gql from 'graphql-tag'\n\nimport { getDirective, MapperKind, mapSchema } from '@graphql-tools/utils'\nimport { logger } from '@things-factory/env'\n\nimport { judgePermission } from '../../utils/check-permission.js'\nimport { noteAuditAction } from '../audit/audit-recorder.js'\nimport { errorCodeOf, returnedCountOf, targetIdsOf } from '../audit/audit-target.js'\nimport { confirmationRefusal, isRecentlyConfirmed } from '../identity-confirmation/identity-confirmation.js'\nimport { declaredAxes, isDeclaredAxis } from './privilege-axis.js'\nimport { privilegeRejection } from './privilege-rejection.js'\nimport {\n coverageOf,\n DeclaringModule,\n enforcementMode,\n EnforcementMode,\n judgeUndeclared,\n modulesFromLoader\n} from './open-field-rule.js'\n\nprocess['PRIVILEGES'] = {}\n\n/** The axis check every declaration passes, whoever declares it — `@privilege` or `declarePrivileges`. */\nfunction checkAxis(where: string, privilege: string, how: string) {\n /*\n * The axis has to be one this installation declared.\n *\n * Without this, `privilege: \"mutaiton\"` registered a pair nobody would ever be granted\n * — a gate shut forever, with no error to read. The list is not the framework's: see\n * `privilege-axis.ts` for why, and for the fact that it must be declared at module\n * import time rather than on a bootstrap hook.\n */\n if (!isDeclaredAxis(privilege)) {\n throw new Error(\n `${how} on ${where} uses axis \"${privilege}\", which this installation does not declare. ` +\n `Declared axes: ${[...declaredAxes()].sort().join(', ')}. ` +\n `Fix the spelling, or call declareAxes(['${privilege}']) at the top level of the module's ` +\n `server/index.ts — a bootstrap hook runs after the schema is built and is too late.`\n )\n }\n}\n\n/**\n * Declares privileges a module asks in code (`checkPermission`) and no field asks with `@privilege` — a rule an issued\n * document kind or a worklist step holds. The privilege sync creates rows only for what is declared, and a role task\n * naming an undeclared pair is refused when a template is applied (ADR-0176, 2026-10-30: `employee-certificate` was\n * asked in code only, and `office.finance` could not be applied).\n *\n * Call it at the top level of the file that asks them, as `declareAxes` - before the schema is built.\n */\nexport function declarePrivileges(where: string, pairs: [category: string, privilege: string][]): void {\n for (const [category, privilege] of pairs) {\n if (!category || !privilege) throw new Error(`declarePrivileges on ${where} names an empty category or axis`)\n checkAxis(where, privilege, 'declarePrivileges')\n process['PRIVILEGES'][`${category} ${privilege}`] = [category, privilege]\n }\n}\n\n/*\n * ── What each field asks for, by `Type.field` ─────────────────────────────────\n * `PRIVILEGES` above is the list of pairs this installation declares; it cannot answer \"what\n * does `Query.jobOrders` ask for\". Something that reaches a door by another entrance has to ask\n * exactly what the door asks — an AI tool is one (operato-twin ADR-0071 decision 2, ADR-0072\n * decision 5). Without this map each caller copied the pair by hand, and a copy drifts the day\n * the door's declaration changes.\n *\n * Three answers, and they are not the same:\n * - not in the map the schema has no such root field. A caller that named it has a typo,\n * and reading that as \"open\" is how a gate opens without an error.\n * - `null` the field exists and declares nothing. It is open.\n * - a gate what `checkPermission` is asked at that field.\n *\n * Every root field is recorded (Query / Mutation / Subscription) so the first two can be told\n * apart; a field of any other type is recorded only when it carries the directive.\n * Kept on `process` for the same reason `PRIVILEGES` is.\n */\nprocess['PRIVILEGE_OF_FIELD'] = {}\n\n/** What `checkPermission` is asked at a field — the same four things the directive passes it. */\nexport interface FieldGate {\n category?: string\n privilege?: string\n owner: boolean\n super: boolean\n}\n\n/**\n * What the field `Type.field` asks for. Valid once the schema has been built.\n *\n * `known: false` means the schema has no such root field — treat it as a mistake, never as open.\n */\nexport function privilegeOfField(typeName: string, fieldName: string): { known: false } | { known: true; gate: FieldGate | null } {\n const map = process['PRIVILEGE_OF_FIELD'] as Record<string, FieldGate | null>\n const where = `${typeName}.${fieldName}`\n return where in map ? { known: true, gate: map[where] } : { known: false }\n}\n\nconst DIRECTIVE = 'privilege'\n\n/**\n * ⚠ **다음에 목록 인자를 붙이는 사람에게.**\n *\n * 여기 `legacy` 인자가 있었다 — 권한 이름을 옮기는 동안 옛 이름도 받아 주는 별칭이었다.\n * **걷어냈다.** 이 저장소는 대개조 중이고 **호환 계층을 끼우지 않는다**: 이름을 바꾸면 바꾼\n * 것이고, 부여는 관리자가 다시 놓는다. 별칭은 「한동안」이 영원이 되는 길이었다.\n *\n * 곧 필요해지는 목록 인자는 **AND** 다(`docs/design/auth-rebuild.md` §1-(3)): 외부에서\n * 당겨오면서 남의 데이터를 앉히는 호출은 `execute` **와** 그 모듈의 `mutation` 을 **둘 다**\n * 요구해야 한다.\n *\n * 그것을 `privileges: [...]` 처럼 중립적으로 이름 지으면 다음 사람이 「이 중 하나」로 읽고,\n * 그렇게 쓰는 날 게이트가 **오류 없이** 열린다. `requiresAll: [...]` 처럼 **이름이 AND 라고\n * 말하게** 한다.\n */\nexport const privilegeDirectiveTypeDefs = gql`\n directive @privilege(\n category: String\n privilege: String\n domainOwnerGranted: Boolean\n superUserGranted: Boolean\n ) on FIELD_DEFINITION\n`\n/**\n * The server calls this with the merged schema only. `modules` and `mode` are for tests, which\n * have no module walk of their own (`orderedModuleNames` is empty under jest) — see `open-fields.ts`.\n */\nexport const privilegeDirectiveResolver = (\n schema: GraphQLSchema,\n options: { modules?: DeclaringModule[]; mode?: EnforcementMode } = {}\n) => {\n const coverage = coverageOf(options.modules ?? modulesFromLoader())\n const mode = options.mode ?? enforcementMode()\n const unlisted: string[] = []\n\n const mapped = mapSchema(schema, {\n [MapperKind.OBJECT_FIELD]: (fieldConfig, fieldName, typeName, schema) => {\n const privilegeDirective = getDirective(schema, fieldConfig, DIRECTIVE)?.[0]\n /* A door that also asks for a recent confirmation that it is still the person (ADR-0168). */\n const asksConfirmation = !!getDirective(schema, fieldConfig, 'recentConfirmation')?.[0]\n\n if (asksConfirmation && !privilegeDirective) {\n throw new Error(\n `@recentConfirmation on ${typeName}.${fieldName} has no @privilege beside it. The confirmation is asked by ` +\n `the privilege gate, after the privilege - a door that asks only for it would ask nobody.`\n )\n }\n\n /* A root field with no directive is recorded as open, so \"open\" and \"no such field\" differ. */\n if (!privilegeDirective && isRootType(schema, typeName)) {\n const where = `${typeName}.${fieldName}`\n\n process['PRIVILEGE_OF_FIELD'][where] = null\n\n /*\n * ── The field that arrived without saying anything ───────────────────\n * Its module opted in (declared `openFields`) and names it in neither list. That is how\n * `deleteAppBinding` went in, and the whole point of §8 step 1 is that it cannot happen\n * quietly any more. A field of a module that has not opted in is left exactly as before.\n */\n if (judgeUndeclared(where, coverage) === 'unlisted') {\n if (mode === 'boot') {\n unlisted.push(where)\n } else {\n refuseUnlisted(fieldConfig, where)\n }\n }\n }\n\n if (privilegeDirective) {\n const { resolve = defaultFieldResolver, args } = fieldConfig\n\n if (!args) {\n throw new Error(`Unexpected Error. args should be defined in @privilege directive for field ${fieldName}.`)\n }\n\n const { domainOwnerGranted, superUserGranted, category, privilege } = privilegeDirective\n const where = `${typeName}.${fieldName}`\n\n /*\n * The audit's name for this door (ADR-0141 §3.2), and what the field says it acts on (§3.3).\n * A door that asks ownership only is named by the ownership it asks.\n */\n const door =\n category && privilege\n ? `${category}:${privilege}`\n : [domainOwnerGranted && 'owner', superUserGranted && 'super'].filter(Boolean).join('+')\n const target = getDirective(schema, fieldConfig, 'auditTarget')?.[0] as { kind: string; arg: string } | undefined\n\n /*\n * A declaration has to name something.\n *\n * `category` and `privilege` are one thing, not two: together they name a row in the\n * privilege table, and either alone names no row, so `User.hasPrivilege` is never\n * reached and the field falls back on ownership flags it did not set.\n */\n if (!category !== !privilege) {\n throw new Error(\n `@privilege on ${where} gives ${category ? 'a category with no privilege' : 'a privilege with no category'}. ` +\n `The pair names the privilege to look for; one half names none.`\n )\n }\n\n /*\n * `@privilege()` with nothing in it reads like a gate and guards nothing. Until\n * 2026-09-15 what it did depended on where the caller sat: `checkPermission` answered\n * false from a safe address and refused everyone, true from an unsafe one and let\n * everyone through. Both are false now, so the shape is merely useless rather than\n * dangerous — and a field that is open should say so by carrying no directive, not by\n * carrying an empty one.\n *\n * It is also the shape someone reaches for wanting \"being signed in is enough\". That\n * is a real thing to want and this directive does not express it; the answer settled\n * on 2026-09-15 is a category for the published side of a module, `<module>-published`.\n *\n * Throwing stops the boot, which is what §6-2 of docs/design/auth-rebuild.md settled\n * for a resolver that declares nothing. A decorator that declares nothing is that\n * same resolver wearing one.\n */\n if (!category && !privilege && !domainOwnerGranted && !superUserGranted) {\n throw new Error(\n `@privilege on ${where} declares nothing. ` +\n `Name (category, privilege) for a privilege gate, or domainOwnerGranted / superUserGranted for an ` +\n `ownership gate. A field open to everyone carries no directive at all.`\n )\n }\n\n if (privilege) checkAxis(where, privilege, '@privilege')\n\n if (category && privilege) {\n process['PRIVILEGES'][`${category} ${privilege}`] = [category, privilege]\n }\n\n /* After every refusal above, so a declaration that names nothing never lands here. */\n process['PRIVILEGE_OF_FIELD'][where] = {\n category: category || undefined,\n privilege: privilege || undefined,\n owner: !!domainOwnerGranted,\n super: !!superUserGranted\n } satisfies FieldGate\n\n // 필드의 기존 description 가져오기\n const existingDescription = fieldConfig.description || ''\n\n // 권한 정보를 포함한 새로운 description 생성\n const privilegeDescription =\n `\\n\\n🔒 Requires privilege: ${category}:${privilege}` +\n (domainOwnerGranted ? ', Domain ownership' : '') +\n (superUserGranted ? ', System ownership' : '') +\n (asksConfirmation ? ', a recent confirmation that it is the person' : '')\n\n // 기존 description과 결합\n fieldConfig.description = `${existingDescription} ${privilegeDescription}`.trim()\n\n fieldConfig.resolve = async function (source, args, context, info) {\n const { domain, user, unsafeIP, prohibitedPrivileges } = context.state\n\n const judgement = await judgePermission(\n {\n category,\n privilege,\n owner: domainOwnerGranted,\n super: superUserGranted\n },\n user,\n domain,\n unsafeIP,\n prohibitedPrivileges\n )\n\n const targetKind = target?.kind\n const targetIds = target ? targetIdsOf(args, target.arg) : undefined\n const targetRole = target ? ('requested' as const) : undefined\n\n if (judgement.permitted === true) {\n /*\n * The privilege is the person's; the confirmation says the person is the one at the screen (ADR-0168).\n * Passing does not lengthen it - it ends ten minutes after it was given.\n */\n if (asksConfirmation && !isRecentlyConfirmed(context, user?.id)) {\n noteAuditAction({ kind: 'door.check', door, decision: 'denied', basis: 'identity-confirmation', targetKind, targetIds, targetRole })\n throw confirmationRefusal(context)\n }\n\n noteAuditAction({ kind: 'door.check', door, decision: 'granted', basis: judgement.by, targetKind, targetIds, targetRole })\n\n /* Passing the door is not doing the work - what the work came to is its own row (§3.2). */\n try {\n const result = await resolve.call(this, source, args, context, info)\n noteAuditAction({ kind: 'door.result', door, outcome: 'ok', returned: returnedCountOf(result), targetKind, targetIds, targetRole })\n return result\n } catch (error) {\n noteAuditAction({ kind: 'door.result', door, outcome: 'error', code: errorCodeOf(error), targetKind, targetIds, targetRole })\n throw error\n }\n }\n\n noteAuditAction({ kind: 'door.check', door, decision: 'denied', basis: judgement.because, targetKind, targetIds, targetRole })\n\n /*\n * 안 열렸으면 **거기서 끝이다.**\n *\n * 여기 옛 이름으로 한 번 더 보는 길이 있었다. 그것을 걷어냈다 — 호환 계층을 끼우지\n * 않는다. 이름을 옮기면 부여도 옮기는 것이고, 그 일은 관리자가 역할 화면에서 한다.\n *\n * 문장 만들기는 `privilege-rejection.ts` 가 소유한다.\n */\n throw privilegeRejection(context, category, privilege, judgement.because, info?.operation?.operation)\n }\n\n /*\n * ── A subscription is opened by `subscribe`, not `resolve` ────────────\n * Wrapping only `resolve` left a declared subscription connectable by anyone: the stream\n * opened and every event then failed. It leaked nothing, and it refused nothing either.\n * The same question is asked where the stream starts.\n */\n if (fieldConfig.subscribe) {\n const subscribe = fieldConfig.subscribe\n\n fieldConfig.subscribe = async function (source, args, context, info) {\n const { domain, user, unsafeIP, prohibitedPrivileges } = context.state\n\n const judgement = await judgePermission(\n { category, privilege, owner: domainOwnerGranted, super: superUserGranted },\n user,\n domain,\n unsafeIP,\n prohibitedPrivileges\n )\n\n if (judgement.permitted === false) {\n throw privilegeRejection(context, category, privilege, judgement.because, 'subscription')\n }\n\n return await subscribe.call(this, source, args, context, info)\n }\n }\n\n return fieldConfig\n }\n }\n })\n\n /*\n * Every unlisted field at once, rather than the first one. The person who meets this has usually\n * added several resolvers together, and fixing them one boot at a time is how a list gets\n * abandoned half done.\n */\n if (unlisted.length) {\n throw new Error(\n `${unlisted.length} field(s) declare no @privilege and are not listed as open by their module:\\n` +\n unlisted.map(where => ` ${where}`).join('\\n') +\n `\\n\\nFor each, either give it @privilege(category: …, privilege: …), or name it in the module's ` +\n `schema.openFields — under byDesign with the reason it is open, or under notYetDeclared if it ` +\n `is waiting to be closed. See docs/design/auth-rebuild.md §8.`\n )\n }\n\n return mapped\n}\n\n/**\n * Production's answer to an unlisted field: that field refuses, and says so in the log once.\n *\n * The server stays up. What cannot happen is the field answering — it arrived without saying who\n * may call it, and the answer to that is nobody until somebody says.\n */\nconst reported = new Set<string>()\n\nfunction refuseUnlisted(fieldConfig: any, where: string) {\n const refuse = () => {\n if (!reported.has(where)) {\n reported.add(where)\n logger.error(\n `${where} declares no @privilege and is not listed in its module's schema.openFields — refusing it.`\n )\n }\n\n return new GraphQLError(`${where} is not available: it declares no privilege.`, {\n extensions: { code: 'FORBIDDEN', refusal: { code: 'field-declares-no-privilege', params: { field: where } } }\n })\n }\n\n fieldConfig.resolve = async () => {\n throw refuse()\n }\n\n if (fieldConfig.subscribe) {\n fieldConfig.subscribe = async () => {\n throw refuse()\n }\n }\n}\n\nfunction isRootType(schema: GraphQLSchema, typeName: string): boolean {\n return [schema.getQueryType(), schema.getMutationType(), schema.getSubscriptionType()].some(\n root => root?.name === typeName\n )\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"privilege-mutation.js","sourceRoot":"","sources":["../../../server/service/privilege/privilege-mutation.ts"],"names":[],"mappings":";;;;AAAA,+CAAsE;AACtE,qCAA4B;AAE5B,iDAAqD;AAErD,6CAAsC;AACtC,iDAA0C;AAC1C,6DAAmE;AAG5D,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAKtB,AAAN,KAAK,CAAC,0BAA0B,CACZ,SAAuB,EAClC,OAAwB;QAE/B,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;QACxC,MAAM,mBAAmB,GAAG,IAAA,qBAAa,EAAC,wBAAS,CAAC,CAAA;QAEpD,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,UAA8B,CAAC,EAAE,CAAC;YAC7E,IAAI,CAAC,IAAI,CAAC,MAAM,mBAAmB,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;gBAC1E,MAAM,mBAAmB,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;YACpD,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;IAIK,AAAN,KAAK,CAAC,eAAe,CACD,SAAuB,EAClC,OAAwB;QAE/B,IAAI,SAAS,CAAC,KAAK,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAC9C,SAAS,CAAC,KAAK,GAAG,MAAM,IAAA,qBAAa,EAAC,cAAI,CAAC,CAAC,MAAM,CAAC;gBACjD,EAAE,EAAE,IAAA,YAAE,EAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAmB,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;aAC9D,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,MAAM,IAAA,qBAAa,EAAC,wBAAS,CAAC,CAAC,IAAI,CAAC;YACzC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI;YAC3B,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI;YAC3B,GAAG,SAAS;SACb,CAAC,CAAA;IACJ,CAAC;IAIK,AAAN,KAAK,CAAC,eAAe,CACN,IAAY,EACR,QAAgB,EACnB,KAAqB,EAC5B,OAAwB;QAE/B,MAAM,UAAU,GAAG,IAAA,qBAAa,EAAC,wBAAS,CAAC,CAAA;QAC3C,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC;YACzC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YACzB,SAAS,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC;SAC3C,CAAC,CAAA;QAEF,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACpD,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACtC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE;gBAC7B,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;oBAC1B,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;gBAClB,CAAC;YACH,CAAC,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,MAAM,UAAU,CAAC,IAAI,CAAC;YAC3B,GAAG,SAAS;YACZ,GAAG,KAAK;YACR,KAAK,EAAE,MAAM,IAAA,qBAAa,EAAC,cAAI,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC;YACnD,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI;SAC5B,CAAC,CAAA;IACJ,CAAC;IAIK,AAAN,KAAK,CAAC,eAAe,CACN,IAAY,EACR,QAAgB,EAC1B,OAAwB;QAE/B,MAAM,IAAA,qBAAa,EAAC,wBAAS,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;QACzD,OAAO,IAAI,CAAA;IACb,CAAC;CACF,CAAA;AAjFY,8CAAiB;AAKtB;IAJL,IAAA,wBAAS,EAAC,mCAAmC,CAAC;IAC9C,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE;QAC5B,WAAW,EAAE,uFAAuF;KACrG,CAAC;IAEC,mBAAA,IAAA,kBAAG,EAAC,WAAW,CAAC,CAAA;IAChB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CADuB,iCAAY;;mEAa1C;AAIK;IAFL,IAAA,wBAAS,EAAC,mCAAmC,CAAC;IAC9C,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,wBAAS,EAAE,EAAE,WAAW,EAAE,yBAAyB,EAAE,CAAC;IAExE,mBAAA,IAAA,kBAAG,EAAC,WAAW,CAAC,CAAA;IAChB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CADuB,iCAAY;;wDAc1C;AAIK;IAFL,IAAA,wBAAS,EAAC,mCAAmC,CAAC;IAC9C,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,wBAAS,EAAE,EAAE,WAAW,EAAE,iCAAiC,EAAE,CAAC;IAEhF,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;IACX,mBAAA,IAAA,kBAAG,EAAC,UAAU,CAAC,CAAA;IACf,mBAAA,IAAA,kBAAG,EAAC,OAAO,CAAC,CAAA;IACZ,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6DADe,mCAAc;;wDAwBpC;AAIK;IAFL,IAAA,wBAAS,EAAC,mCAAmC,CAAC;IAC9C,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,qBAAqB,EAAE,CAAC;IAElE,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;IACX,mBAAA,IAAA,kBAAG,EAAC,UAAU,CAAC,CAAA;IACf,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;wDAIP;4BAhFU,iBAAiB;IAD7B,IAAA,uBAAQ,EAAC,wBAAS,CAAC;GACP,iBAAiB,CAiF7B","sourcesContent":["import { Arg, Ctx, Mutation, Resolver, Directive } from 'type-graphql'\nimport { In } from 'typeorm'\n\nimport { getRepository } from '@things-factory/shell'\n\nimport { Role } from '../role/role.js'\nimport { Privilege } from './privilege.js'\nimport { NewPrivilege, PrivilegePatch } from './privilege-types.js'\n\n@Resolver(Privilege)\nexport class PrivilegeMutation {\n @Directive('@privilege(superUserGranted:true)')\n @Mutation(returns => Boolean, {\n description: 'To synchronize privilege master from graphql directives. Only superuser is permitted.'\n })\n async synchronizePrivilegeMaster(\n @Arg('privilege') privilege: NewPrivilege,\n @Ctx() context: ResolverContext\n ): Promise<Boolean> {\n const privileges = process['PRIVILEGES']\n const privilegeRepository = getRepository(Privilege)\n\n for (const [category, name] of Object.values(privileges as [string, string])) {\n if (0 == (await privilegeRepository.count({ where: { category, name } }))) {\n await privilegeRepository.save({ category, name })\n }\n }\n\n return true\n }\n\n @Directive('@privilege(superUserGranted:true)')\n @Mutation(returns => Privilege, { description: 'To create new privilege' })\n async createPrivilege(\n @Arg('privilege') privilege: NewPrivilege,\n @Ctx() context: ResolverContext\n ): Promise<Privilege> {\n if (privilege.roles && privilege.roles.length) {\n privilege.roles = await getRepository(Role).findBy({\n id: In(privilege.roles.map((role: Partial<Role>) => role.id))\n })\n }\n\n return await getRepository(Privilege).save({\n creator: context.state.user,\n updater: context.state.user,\n ...privilege\n })\n }\n\n @Directive('@privilege(superUserGranted:true)')\n @Mutation(returns => Privilege, { description: 'To modify privilege information' })\n async updatePrivilege(\n @Arg('name') name: string,\n @Arg('category') category: string,\n @Arg('patch') patch: PrivilegePatch,\n @Ctx() context: ResolverContext\n ): Promise<Privilege> {\n const repository = getRepository(Privilege)\n const privilege = await repository.findOne({\n where: { name, category },\n relations: ['roles', 'creator', 'updater']\n })\n\n const roleIds = privilege.roles.map(role => role.id)\n if (patch.roles && patch.roles.length) {\n patch.roles.forEach(({ id }) => {\n if (!roleIds.includes(id)) {\n roleIds.push(id)\n }\n })\n }\n\n return await repository.save({\n ...privilege,\n ...patch,\n roles: await getRepository(Role).findByIds(roleIds),\n updater: context.state.user\n })\n }\n\n @Directive('@privilege(superUserGranted:true)')\n @Mutation(returns => Boolean, { description: 'To delete privilege' })\n async deletePrivilege(\n @Arg('name') name: string,\n @Arg('category') category: string,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n await getRepository(Privilege).delete({ name, category })\n return true\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"privilege-query.js","sourceRoot":"","sources":["../../../server/service/privilege/privilege-query.ts"],"names":[],"mappings":";;;;AAAA,+CAA8F;AAC9F,iDAAuG;AAEvG,6CAAsC;AACtC,6CAAsC;AACtC,iDAA0C;AAC1C,yEAAkE;AAClE,6DAAoD;AAG7C,IAAM,cAAc,GAApB,MAAM,cAAc;IAGnB,AAAN,KAAK,CAAC,UAAU,CACW,MAAiB,EACnC,OAAwB;QAE/B,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,IAAA,qCAA6B,EAAC;YACzD,MAAM;YACN,UAAU,EAAE,IAAA,qBAAa,EAAC,wBAAS,CAAC;YACpC,KAAK,EAAE,GAAG;YACV,WAAW,EAAE,CAAC,WAAW,EAAE,UAAU,CAAC;YACtC,UAAU,EAAE;gBACV,SAAS,EAAE;oBACT,UAAU,EAAE,MAAM;iBACnB;aACF;SACF,CAAC;aACC,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC;aAC5B,eAAe,EAAE,CAAA;QAEpB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;IACzB,CAAC;IAGK,AAAN,KAAK,CAAC,YAAY,CACE,SAAiB,EAClB,QAAgB,EAC1B,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QACtC,OAAO,MAAM,cAAI,CAAC,YAAY,CAAC,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;IACnE,CAAC;IAGK,AAAN,KAAK,CAAC,oBAAoB,CACN,SAAiB,EAClB,QAAgB,EAC1B,OAAwB;QAE/B,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAC9B,OAAO,MAAM,cAAI,CAAC,uBAAuB,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAA;IACtE,CAAC;IAGK,AAAN,KAAK,CAAC,WAAW,CAAS,SAAoB,EAAS,OAAwB;QAC7E,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,CAAA;QACrB,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAA;QAEpC,MAAM,OAAO,GAAG,kBAAkB,IAAI,EAAE,CAAA;QACxC,MAAM,WAAW,GAAG,sBAAsB,QAAQ,EAAE,CAAA;QACpD,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,CAAA;QACxB,MAAM,SAAS,GAAG,CAAC,CAAC,WAAW,CAAC,CAAA;QAEhC,OAAO,CAAC,CAAC,uBAAuB,EAAE;YAChC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK;YACtC,QAAQ,EAAE,SAAS,KAAK,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;SAC3D,CAAC,CAAA;IACJ,CAAC;IAGK,AAAN,KAAK,CAAC,SAAS,CAAS,SAAoB,EAAS,OAAwB;QAC3E,OAAO,SAAS,CAAC,IAAI,CAAA;IACvB,CAAC;IAED;;;;;;OAMG;IAOG,AAAN,KAAK,CAAC,UAAU,CAAS,SAAoB;QAC3C,OAAO,IAAA,gDAAqB,EAAC,OAAO,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC,CAAA;IAChE,CAAC;IAGK,AAAN,KAAK,CAAC,KAAK,CAAS,SAAoB;QACtC,OAAO,CACL,MAAM,IAAA,qBAAa,EAAC,wBAAS,CAAC,CAAC,OAAO,CAAC;YACrC,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,CAAC,EAAE,EAAE;YAC3B,SAAS,EAAE,CAAC,OAAO,CAAC;SACrB,CAAC,CACH,CAAC,KAAK,CAAA;IACT,CAAC;IAGK,AAAN,KAAK,CAAC,OAAO,CAAS,SAAoB;QACxC,OAAO,MAAM,IAAA,qBAAa,EAAC,cAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,SAAS,CAAC,SAAS,EAAE,CAAC,CAAA;IACzE,CAAC;IAGK,AAAN,KAAK,CAAC,OAAO,CAAS,SAAoB;QACxC,OAAO,MAAM,IAAA,qBAAa,EAAC,cAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,SAAS,CAAC,SAAS,EAAE,CAAC,CAAA;IACzE,CAAC;CACF,CAAA;AArGY,wCAAc;AAGnB;IAFL,IAAA,wBAAS,EAAC,yGAAyG,CAAC;IACpH,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,kCAAa,EAAE,EAAE,WAAW,EAAE,8BAA8B,EAAE,CAAC;IAE9E,mBAAA,IAAA,mBAAI,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAS,CAAC,CAAA;IACvB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAD2B,iBAAS;;gDAkB3C;AAGK;IADL,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,8CAA8C,EAAE,CAAC;IAExF,mBAAA,IAAA,kBAAG,EAAC,WAAW,CAAC,CAAA;IAChB,mBAAA,IAAA,kBAAG,EAAC,UAAU,CAAC,CAAA;IACf,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;kDAIP;AAGK;IADL,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC,cAAM,CAAC,EAAE,EAAE,WAAW,EAAE,gDAAgD,EAAE,CAAC;IAE3F,mBAAA,IAAA,kBAAG,EAAC,WAAW,CAAC,CAAA;IAChB,mBAAA,IAAA,kBAAG,EAAC,UAAU,CAAC,CAAA;IACf,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;0DAIP;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC;IACX,mBAAA,IAAA,mBAAI,GAAE,CAAA;IAAwB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAAjB,wBAAS;;iDAa7C;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC;IACb,mBAAA,IAAA,mBAAI,GAAE,CAAA;IAAwB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAAjB,wBAAS;;+CAE3C;AAeK;IANL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE;QAC9B,WAAW,EACT,iGAAiG;YACjG,sGAAsG;YACtG,gFAAgF;KACnF,CAAC;IACgB,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAY,wBAAS;;gDAE5C;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,cAAI,CAAC,CAAC;IACjB,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAY,wBAAS;;2CAOvC;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,cAAI,CAAC;IACb,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAY,wBAAS;;6CAEzC;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,cAAI,CAAC;IACb,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAY,wBAAS;;6CAEzC;yBApGU,cAAc;IAD1B,IAAA,uBAAQ,EAAC,wBAAS,CAAC;GACP,cAAc,CAqG1B","sourcesContent":["import { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root } from 'type-graphql'\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'\n\nimport { Role } from '../role/role.js'\nimport { User } from '../user/user.js'\nimport { Privilege } from './privilege.js'\nimport { isDeprecatedPrivilege } from './privilege-deprecation.js'\nimport { PrivilegeList } from './privilege-types.js'\n\n@Resolver(Privilege)\nexport class PrivilegeQuery {\n @Directive('@privilege(category: \"privilege\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(returns => PrivilegeList, { description: 'To fetch multiple privileges' })\n async privileges(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<PrivilegeList> {\n const [items, total] = await getQueryBuilderFromListParams({\n params,\n repository: getRepository(Privilege),\n alias: 'p',\n searchables: ['privilege', 'category'],\n filtersMap: {\n privilege: {\n columnName: 'name'\n }\n }\n })\n .orderBy('p.category', 'ASC')\n .getManyAndCount()\n\n return { items, total }\n }\n\n @Query(returns => Boolean, { description: 'To query whether I have the given permission' })\n async hasPrivilege(\n @Arg('privilege') privilege: string,\n @Arg('category') category: string,\n @Ctx() context: ResolverContext\n ): Promise<Boolean> {\n const { domain, user } = context.state\n return await User.hasPrivilege(privilege, category, domain, user)\n }\n\n @Query(returns => [Domain], { description: 'To fetch domains with given privilege for user' })\n async domainsWithPrivilege(\n @Arg('privilege') privilege: string,\n @Arg('category') category: string,\n @Ctx() context: ResolverContext\n ): Promise<Partial<Domain>[]> {\n const { user } = context.state\n return await User.getDomainsWithPrivilege(privilege, category, user)\n }\n\n @FieldResolver(type => String)\n async description(@Root() privilege: Privilege, @Ctx() context: ResolverContext) {\n const { t } = context\n const { name, category } = privilege\n\n const keyname = `privilege.name.${name}`\n const keycategory = `privilege.category.${category}`\n const tname = t(keyname)\n const tcategory = t(keycategory)\n\n return t('privilege.description', {\n name: tname === keyname ? name : tname,\n category: tcategory === keycategory ? category : tcategory\n })\n }\n\n @FieldResolver(type => String)\n async privilege(@Root() privilege: Privilege, @Ctx() context: ResolverContext) {\n return privilege.name\n }\n\n /**\n * **이 배포의 어떤 코드도 더 이상 요구하지 않는 권한인가** — 판정은\n * `privilege-deprecation.ts` 가 소유한다(그 파일에 이유가 있다).\n *\n * 조회 때 계산한다(저장하지 않는다) — 마이그레이션이 없고, 한 DB 를 모듈 구성이 다른 앱 둘이 볼 때도\n * **묻는 배포의 사실**을 답한다.\n */\n @FieldResolver(type => Boolean, {\n description:\n 'True when no module in this deployment declares this privilege anymore (@privilege directive). ' +\n 'The bootstrap sync only adds rows, so a removed directive leaves a grantable row that does nothing. ' +\n 'Computed per request — it answers for the asking deployment, not for all time.'\n })\n async deprecated(@Root() privilege: Privilege): Promise<boolean> {\n return isDeprecatedPrivilege(process['PRIVILEGES'], privilege)\n }\n\n @FieldResolver(type => [Role])\n async roles(@Root() privilege: Privilege) {\n return (\n await getRepository(Privilege).findOne({\n where: { id: privilege.id },\n relations: ['roles']\n })\n ).roles\n }\n\n @FieldResolver(type => User)\n async updater(@Root() privilege: Privilege): Promise<User> {\n return await getRepository(User).findOneBy({ id: privilege.updaterId })\n }\n\n @FieldResolver(type => User)\n async creator(@Root() privilege: Privilege): Promise<User> {\n return await getRepository(User).findOneBy({ id: privilege.creatorId })\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"privilege-rejection.js","sourceRoot":"","sources":["../../../server/service/privilege/privilege-rejection.ts"],"names":[],"mappings":"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","sourcesContent":["import { GraphQLError } from 'graphql'\n\n/*\n * 권한 거절을 만든다 — **사용자의 말로, 코드와 함께.**\n *\n * ── 왜 따로 있나 ────────────────────────────────────────────────────────────\n * 이 문장은 프레임워크 apollo 링크(`@operato/graphql` 의 ERROR_HANDLER)를 타고 **사용자 얼굴까지** 간다\n * — 자동으로 닫히지 않는 오류 토스트다. 그런데 다른 서버 오류가 모두 `context.t` 로 옮겨진 뒤에도\n * 여기만 영어 한 문장(`Unauthorized! twin:mutation privilege required`)이었다.\n *\n * 지시자 안에 인라인으로 두면 테스트가 닿지 못한다(스키마를 짓고 리졸버를 태워야 한다). 위험한 것은\n * 게이트 판정이 아니라 **문장 만들기**다 — 번역기가 없는 컨텍스트, 키가 없는 언어, 형태에 의존하는\n * 소비처. 그래서 순수 함수로 떼어 둔다.\n */\n\n/** 번역이 없으면 영어 문장을 그대로 쓴다. */\nfunction localized(context: any, key: string, params: Record<string, string>, fallback: string): string {\n const t = typeof context?.t === 'function' ? context.t : null\n if (!t) return fallback\n\n let translated: string\n try {\n translated = t(key, params)\n } catch {\n /* 번역기가 던지면 오류의 원인이 번역기로 바뀐다 — 거절은 그대로 전달되어야 한다. */\n return fallback\n }\n\n /*\n * i18next 는 키를 못 찾으면 **키를 그대로 돌려준다.** 그걸 쓰면 사용자가\n * `error.x privilege required` 를 읽게 되므로 영어 문장으로 되돌린다\n * (같은 대비를 `privilege-query.ts` 의 description 도 한다).\n */\n return !translated || translated === key ? fallback : translated\n}\n\n/**\n * 무엇이 필요했는지 — 화면이 **문장을 다시 파싱하지 않고** 안내를 만들 수 있게 실어 보낸다.\n * 문장 형태에 의존하면 번역하는 순간 깨진다.\n */\nexport type PrivilegeRequirement = { category: string; privilege: string } | 'ownership'\n\n/** Why it was refused - see `RefusalCause` in `utils/check-permission.ts`. Only `role` can be asked for (ADR-0103). */\nexport type { RefusalCause } from '../../utils/check-permission.js'\nimport type { RefusalCause } from '../../utils/check-permission.js'\n\n/** The sentence for a named privilege, by why it was refused. `role` keeps the sentence it always had. */\nconst NAMED: Record<RefusalCause, { key: string; fallback: (x: string) => string }> = {\n role: { key: 'error.x privilege required', fallback: x => `unauthorized! ${x} privilege required` },\n address: { key: 'error.x not allowed from this address', fallback: x => `unauthorized! ${x} is not allowed from this address` },\n license: { key: 'error.x not licensed', fallback: x => `unauthorized! ${x} is not licensed on this installation` },\n ownership: { key: 'error.x privilege required', fallback: x => `unauthorized! ${x} privilege required` },\n unknown: { key: 'error.x refused for this request', fallback: x => `unauthorized! ${x} is refused for this request` }\n}\n\n/**\n * 권한 거절 오류. `code: 'FORBIDDEN'` + `requires` + `because` 를 `extensions` 에 담는다.\n *\n * `because` 는 화면이 「권한 요청」을 띄울지 정하는 칸이다 — 역할로 풀리는 것은 `role` 뿐이다.\n * 부르는 쪽이 이유를 모르면(옛 호출) 이름이 있으면 `role`, 없으면 `ownership` 이다 — 지금까지의 뜻 그대로.\n *\n * @param context koa 컨텍스트(요청의 언어를 아는 `t` 를 가진다). 없어도 동작한다.\n */\n/** Which kind of operation was refused - a screen offers an access request only for a change the person made. */\nexport type RefusedOperation = 'query' | 'mutation' | 'subscription'\n\nexport function privilegeRejection(\n context: any,\n category?: string,\n privilege?: string,\n because?: RefusalCause,\n operation?: RefusedOperation\n): GraphQLError {\n const named = !!(category && privilege)\n const requires: PrivilegeRequirement = named ? { category, privilege } : 'ownership'\n const cause: RefusalCause = because ?? (named ? 'role' : 'ownership')\n\n let message: string\n if (named) {\n const x = `${category}:${privilege}`\n const { key, fallback } = NAMED[cause] ?? NAMED.unknown\n message = localized(context, key, { x }, fallback(x))\n } else if (cause === 'address') {\n message = localized(\n context,\n 'error.ownership not allowed from this address',\n {},\n 'unauthorized! ownership does not count from this address'\n )\n } else {\n message = localized(context, 'error.ownership required', {}, 'unauthorized! domain or system ownership required')\n }\n\n return new GraphQLError(message, { extensions: { code: 'FORBIDDEN', requires, because: cause, ...(operation ? { operation } : {}) } })\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"privilege-sync.js","sourceRoot":"","sources":["../../../server/service/privilege/privilege-sync.ts"],"names":[],"mappings":";;AAaA,sDAcC;AA3BD,iDAAiE;AAEjE,iDAA0C;AAE1C;;;;;;;;GAQG;AACI,KAAK,UAAU,qBAAqB,CAAC,QAAoC;IAC9E,OAAO,MAAM,IAAA,kBAAU,EAAC,KAAK,IAAI,EAAE;QACjC,MAAM,UAAU,GAAG,IAAA,qBAAa,EAAC,wBAAS,CAAC,CAAA;QAC3C,MAAM,KAAK,GAAa,EAAE,CAAA;QAE1B,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC;YACxC,IAAI,CAAC,IAAI,CAAC,MAAM,UAAU,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;gBACjE,MAAM,UAAU,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;gBACzC,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC,CAAA;YACnC,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAA;IACd,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { getRepository, inBootTurn } from '@things-factory/shell'\n\nimport { Privilege } from './privilege.js'\n\n/**\n * Writes the privileges the loaded modules declare and the table does not have yet. Returns the ones it\n * added.\n *\n * It takes its turn among the boot-time writers (shell `inBootTurn`). On sqlite every transaction shares\n * one connection: run beside another module's boot transaction, its insert started in the same tick as\n * that one (\"cannot start a transaction within a transaction\") or rode inside it and went when it rolled\n * back. The privilege was then missing again at the next boot, and the collision repeated every boot.\n */\nexport async function synchronizePrivileges(declared: Iterable<[string, string]>): Promise<string[]> {\n return await inBootTurn(async () => {\n const repository = getRepository(Privilege)\n const added: string[] = []\n\n for (const [category, name] of declared) {\n if (0 == (await repository.count({ where: { category, name } }))) {\n await repository.save({ category, name })\n added.push(`${category}/${name}`)\n }\n }\n\n return added\n })\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"privilege-types.js","sourceRoot":"","sources":["../../../server/service/privilege/privilege-types.ts"],"names":[],"mappings":";;;;AAAA,+CAAgE;AAChE,iDAAiD;AACjD,iDAA0C;AAGnC,IAAM,YAAY,GAAlB,MAAM,YAAY;CAYxB,CAAA;AAZY,oCAAY;AAEvB;IADC,IAAA,oBAAK,GAAE;;0CACI;AAGZ;IADC,IAAA,oBAAK,GAAE;;8CACQ;AAGhB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;iDACN;AAGpB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,iBAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;2CAC7B;uBAXP,YAAY;IADxB,IAAA,wBAAS,GAAE;GACC,YAAY,CAYxB;AAGM,IAAM,cAAc,GAApB,MAAM,cAAc;CAe1B,CAAA;AAfY,wCAAc;AAEzB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;0CACf;AAGX;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;4CACb;AAGb;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;gDACT;AAGjB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;mDACN;AAGpB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,iBAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;6CAC5B;yBAdR,cAAc;IAD1B,IAAA,wBAAS,GAAE;GACC,cAAc,CAe1B;AAGM,IAAM,aAAa,GAAnB,MAAM,aAAa;CAMzB,CAAA;AANY,sCAAa;AAExB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,wBAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;4CAC7B;AAGlB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;4CAC1B;wBALF,aAAa;IADzB,IAAA,yBAAU,GAAE;GACA,aAAa,CAMzB;AAGM,IAAM,aAAa,GAAnB,MAAM,aAAa;CAYzB,CAAA;AAZY,sCAAa;AAExB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;sCACtB,MAAM;yCAAA;AAGV;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;sCACpB,MAAM;2CAAA;AAGZ;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;sCACb,MAAM;kDAAA;AAGnB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;sCAChB,OAAO;+CAAA;wBAXN,aAAa;IADzB,IAAA,yBAAU,GAAE;GACA,aAAa,CAYzB","sourcesContent":["import { ObjectType, InputType, Field, Int } from 'type-graphql'\nimport { ObjectRef } from '@things-factory/shell'\nimport { Privilege } from './privilege.js'\n\n@InputType()\nexport class NewPrivilege {\n @Field()\n name: string\n\n @Field()\n category: string\n\n @Field({ nullable: true })\n description?: string\n\n @Field(type => [ObjectRef], { nullable: true })\n roles: ObjectRef[]\n}\n\n@InputType()\nexport class PrivilegePatch {\n @Field({ nullable: true })\n id?: string\n\n @Field({ nullable: true })\n name?: string\n\n @Field({ nullable: true })\n category?: string\n\n @Field({ nullable: true })\n description?: string\n\n @Field(type => [ObjectRef], { nullable: true })\n roles?: ObjectRef[]\n}\n\n@ObjectType()\nexport class PrivilegeList {\n @Field(type => [Privilege], { nullable: true })\n items: Privilege[]\n\n @Field(type => Int, { nullable: true })\n total: number\n}\n\n@ObjectType()\nexport class UserPrivilege {\n @Field({ nullable: true })\n id: String\n\n @Field({ nullable: true })\n name: String\n\n @Field({ nullable: true })\n description: String\n\n @Field({ nullable: true })\n assigned: Boolean\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"privilege.js","sourceRoot":"","sources":["../../../server/service/privilege/privilege.ts"],"names":[],"mappings":";;;;AAAA,qCAWgB;AAChB,+CAA+D;AAC/D,6CAAsC;AACtC,6CAAsC;AAG/B,IAAM,eAAe,GAArB,MAAM,eAAe;CAY3B,CAAA;AAZY,0CAAe;AAE1B;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,4BAA4B,EAAE,CAAC;;kDACnD;AAGlB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,gCAAgC,EAAE,CAAC;;iDACxD;AAGjB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,6CAA6C,EAAE,CAAC;;8CACvE;AAGf;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,gDAAgD,EAAE,CAAC;;8CAC1E;0BAXJ,eAAe;IAD3B,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,oDAAoD,EAAE,CAAC;GACrE,eAAe,CAY3B;AAGM,IAAM,cAAc,GAApB,MAAM,cAAc;CAY1B,CAAA;AAZY,wCAAc;AAEzB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,4BAA4B,EAAE,CAAC;;iDACnD;AAGlB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,gCAAgC,EAAE,CAAC;;gDACxD;AAGjB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,6CAA6C,EAAE,CAAC;;6CACvE;AAGf;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,gDAAgD,EAAE,CAAC;;6CAC1E;yBAXJ,cAAc;IAD1B,IAAA,wBAAS,EAAC,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC;GAC3C,cAAc,CAY1B;AAOM,IAAM,SAAS,GAAf,MAAM,SAAS;CAkDrB,CAAA;AAlDY,8BAAS;AAGpB;IAFC,IAAA,gCAAsB,EAAC,MAAM,CAAC;IAC9B,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAE,EAAE,EAAE,WAAW,EAAE,sCAAsC,EAAE,CAAC;;qCACjE;AAIV;IAFC,IAAA,gBAAM,GAAE;IACR,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,4BAA4B,EAAE,CAAC;;uCACzC;AAIZ;IAFC,IAAA,gBAAM,GAAE;IACR,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,2DAA2D,EAAE,CAAC;;2CACpF;AAMhB;IAJC,IAAA,gBAAM,EAAC;QACN,QAAQ,EAAE,IAAI;KACf,CAAC;IACD,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,sDAAsD,EAAE,CAAC;;8CAC5E;AAUnB;IARC,IAAA,oBAAU,EAAC,IAAI,CAAC,EAAE,CAAC,cAAI,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC;IACjD,IAAA,mBAAS,EAAC;QACT,uFAAuF;QACvF,IAAI,EAAE,kBAAkB;QACxB,WAAW,EAAE,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,oBAAoB,EAAE,IAAI,EAAE,CAAC;QACpE,kBAAkB,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,oBAAoB,EAAE,IAAI,EAAE,CAAC;KACvE,CAAC;IACD,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,cAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,oCAAoC,EAAE,CAAC;;wCAChF;AAIb;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC3C,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,cAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,qCAAqC,EAAE,CAAC;sCACnF,cAAI;0CAAA;AAGb;IADC,IAAA,oBAAU,EAAC,CAAC,SAAoB,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC;;4CACvC;AAIjB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC3C,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,cAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,0CAA0C,EAAE,CAAC;sCACxF,cAAI;0CAAA;AAGb;IADC,IAAA,oBAAU,EAAC,CAAC,SAAoB,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC;;4CACvC;AAIjB;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,+CAA+C,EAAE,CAAC;sCAC7E,IAAI;4CAAA;AAIf;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,oDAAoD,EAAE,CAAC;sCAClF,IAAI;4CAAA;oBAjDJ,SAAS;IALrB,IAAA,gBAAM,GAAE;IACR,IAAA,eAAK,EAAC,gBAAgB,EAAE,CAAC,SAAoB,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,QAAQ,CAAC,EAAE;QACvF,MAAM,EAAE,KAAK;KACd,CAAC;IACD,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,0EAA0E,EAAE,CAAC;GAC3F,SAAS,CAkDrB","sourcesContent":["import {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n ManyToMany,\n ManyToOne,\n JoinTable,\n RelationId,\n PrimaryGeneratedColumn,\n UpdateDateColumn\n} from 'typeorm'\nimport { ObjectType, InputType, Field, ID } from 'type-graphql'\nimport { Role } from '../role/role.js'\nimport { User } from '../user/user.js'\n\n@ObjectType({ description: 'Represents a privilege object with its properties.' })\nexport class PrivilegeObject {\n @Field({ nullable: true, description: 'The name of the privilege.' })\n privilege?: string\n\n @Field({ nullable: true, description: 'The category of the privilege.' })\n category?: string\n\n @Field({ nullable: true, description: 'Indicates if the privilege is for an owner.' })\n owner?: boolean\n\n @Field({ nullable: true, description: 'Indicates if the privilege is for a superuser.' })\n super?: boolean\n}\n\n@InputType({ description: 'Input for privilege data.' })\nexport class PrivilegeInput {\n @Field({ nullable: true, description: 'The name of the privilege.' })\n privilege?: string\n\n @Field({ nullable: true, description: 'The category of the privilege.' })\n category?: string\n\n @Field({ nullable: true, description: 'Indicates if the privilege is for an owner.' })\n owner?: boolean\n\n @Field({ nullable: true, description: 'Indicates if the privilege is for a superuser.' })\n super?: boolean\n}\n\n@Entity()\n@Index('ix_privilege_0', (privilege: Privilege) => [privilege.name, privilege.category], {\n unique: false\n})\n@ObjectType({ description: 'A privilege that can be granted to roles to control access to resources.' })\nexport class Privilege {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier for the privilege.' })\n id: string\n\n @Column()\n @Field({ description: 'The name of the privilege.' })\n name: string\n\n @Column()\n @Field({ nullable: true, description: 'The category of the privilege (e.g., security, resource).' })\n category: string\n\n @Column({\n nullable: true\n })\n @Field({ nullable: true, description: 'A detailed description of what the privilege allows.' })\n description: string\n\n @ManyToMany(type => Role, role => role.privileges)\n @JoinTable({\n /* case M2M, JoinTable setting should be defined only one side (never set both side) */\n name: 'roles_privileges',\n joinColumns: [{ name: 'privileges_id', referencedColumnName: 'id' }],\n inverseJoinColumns: [{ name: 'roles_id', referencedColumnName: 'id' }]\n })\n @Field(type => [Role], { nullable: true, description: 'Roles that include this privilege.' })\n roles: Role[]\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who created the privilege.' })\n creator: User\n\n @RelationId((privilege: Privilege) => privilege.creator)\n creatorId: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who last updated the privilege.' })\n updater: User\n\n @RelationId((privilege: Privilege) => privilege.updater)\n updaterId: string\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'The timestamp when the privilege was created.' })\n createdAt: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'The timestamp when the privilege was last updated.' })\n updatedAt: Date\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/role/index.ts"],"names":[],"mappings":";;;AAAA,uCAAgC;AAChC,mDAA2C;AAC3C,yDAAiD;AACjD,uEAA8D;AAEjD,QAAA,QAAQ,GAAG,CAAC,cAAI,CAAC,CAAA;AACjB,QAAA,SAAS,GAAG,CAAC,yBAAS,EAAE,+BAAY,EAAE,4CAAkB,CAAC,CAAA","sourcesContent":["import { Role } from './role.js'\nimport { RoleQuery } from './role-query.js'\nimport { RoleMutation } from './role-mutation.js'\nimport { RolePrivilegeQuery } from './role-privilege-query.js'\n\nexport const entities = [Role]\nexport const resolvers = [RoleQuery, RoleMutation, RolePrivilegeQuery]\n"]}