@selvajs/server 1.5.0-beta.9 → 2.0.0-beta.16

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 (143) hide show
  1. package/dist/access/guards.d.ts +0 -10
  2. package/dist/access/guards.d.ts.map +1 -1
  3. package/dist/access/guards.js +23 -26
  4. package/dist/access/guards.js.map +1 -1
  5. package/dist/api/bodies.d.ts +1 -1
  6. package/dist/api/bodies.d.ts.map +1 -1
  7. package/dist/api/bodies.js +2 -1
  8. package/dist/api/bodies.js.map +1 -1
  9. package/dist/api/idempotency.d.ts +10 -3
  10. package/dist/api/idempotency.d.ts.map +1 -1
  11. package/dist/api/idempotency.js +32 -9
  12. package/dist/api/idempotency.js.map +1 -1
  13. package/dist/api/index.d.ts +2 -2
  14. package/dist/api/index.d.ts.map +1 -1
  15. package/dist/api/index.js +2 -2
  16. package/dist/api/index.js.map +1 -1
  17. package/dist/api/request.d.ts +12 -4
  18. package/dist/api/request.d.ts.map +1 -1
  19. package/dist/api/request.js +32 -5
  20. package/dist/api/request.js.map +1 -1
  21. package/dist/api/respond.d.ts.map +1 -1
  22. package/dist/api/respond.js +11 -7
  23. package/dist/api/respond.js.map +1 -1
  24. package/dist/api/scope.d.ts +7 -0
  25. package/dist/api/scope.d.ts.map +1 -1
  26. package/dist/api/scope.js +15 -1
  27. package/dist/api/scope.js.map +1 -1
  28. package/dist/compute/idempotency.d.ts +8 -1
  29. package/dist/compute/idempotency.d.ts.map +1 -1
  30. package/dist/compute/idempotency.js +35 -5
  31. package/dist/compute/idempotency.js.map +1 -1
  32. package/dist/compute/index.d.ts +1 -1
  33. package/dist/compute/index.d.ts.map +1 -1
  34. package/dist/compute/index.js +1 -1
  35. package/dist/compute/index.js.map +1 -1
  36. package/dist/compute/limits.d.ts +0 -7
  37. package/dist/compute/limits.d.ts.map +1 -1
  38. package/dist/compute/limits.js +0 -1
  39. package/dist/compute/limits.js.map +1 -1
  40. package/dist/compute/server-config-write.d.ts +11 -0
  41. package/dist/compute/server-config-write.d.ts.map +1 -1
  42. package/dist/compute/server-config-write.js +34 -0
  43. package/dist/compute/server-config-write.js.map +1 -1
  44. package/dist/definitions/definition-service.d.ts.map +1 -1
  45. package/dist/definitions/definition-service.js +3 -2
  46. package/dist/definitions/definition-service.js.map +1 -1
  47. package/dist/definitions/index.d.ts +1 -1
  48. package/dist/definitions/index.d.ts.map +1 -1
  49. package/dist/definitions/index.js +1 -1
  50. package/dist/definitions/index.js.map +1 -1
  51. package/dist/definitions/load-for-render.d.ts +9 -0
  52. package/dist/definitions/load-for-render.d.ts.map +1 -1
  53. package/dist/definitions/load-for-render.js +1 -1
  54. package/dist/definitions/load-for-render.js.map +1 -1
  55. package/dist/definitions/visibility.d.ts.map +1 -1
  56. package/dist/definitions/visibility.js +7 -12
  57. package/dist/definitions/visibility.js.map +1 -1
  58. package/dist/handlers/apiTokens.d.ts.map +1 -1
  59. package/dist/handlers/apiTokens.js +3 -1
  60. package/dist/handlers/apiTokens.js.map +1 -1
  61. package/dist/handlers/definitionVersions.d.ts.map +1 -1
  62. package/dist/handlers/definitionVersions.js +2 -2
  63. package/dist/handlers/definitionVersions.js.map +1 -1
  64. package/dist/handlers/definitions.d.ts.map +1 -1
  65. package/dist/handlers/definitions.js +27 -15
  66. package/dist/handlers/definitions.js.map +1 -1
  67. package/dist/handlers/index.d.ts +1 -1
  68. package/dist/handlers/index.d.ts.map +1 -1
  69. package/dist/handlers/index.js +1 -1
  70. package/dist/handlers/index.js.map +1 -1
  71. package/dist/handlers/invite-lookup.d.ts.map +1 -1
  72. package/dist/handlers/invite-lookup.js +3 -5
  73. package/dist/handlers/invite-lookup.js.map +1 -1
  74. package/dist/handlers/invites.d.ts +4 -3
  75. package/dist/handlers/invites.d.ts.map +1 -1
  76. package/dist/handlers/invites.js +17 -3
  77. package/dist/handlers/invites.js.map +1 -1
  78. package/dist/handlers/oauthConsent.d.ts +25 -13
  79. package/dist/handlers/oauthConsent.d.ts.map +1 -1
  80. package/dist/handlers/oauthConsent.js +29 -13
  81. package/dist/handlers/oauthConsent.js.map +1 -1
  82. package/dist/handlers/orgAssets.d.ts.map +1 -1
  83. package/dist/handlers/orgAssets.js +2 -2
  84. package/dist/handlers/orgAssets.js.map +1 -1
  85. package/dist/handlers/orgCompute.d.ts.map +1 -1
  86. package/dist/handlers/orgCompute.js +4 -2
  87. package/dist/handlers/orgCompute.js.map +1 -1
  88. package/dist/handlers/orgMembers.d.ts.map +1 -1
  89. package/dist/handlers/orgMembers.js +76 -56
  90. package/dist/handlers/orgMembers.js.map +1 -1
  91. package/dist/handlers/ownerChanges.d.ts +8 -0
  92. package/dist/handlers/ownerChanges.d.ts.map +1 -0
  93. package/dist/handlers/ownerChanges.js +19 -0
  94. package/dist/handlers/ownerChanges.js.map +1 -0
  95. package/dist/handlers/projectMembers.d.ts.map +1 -1
  96. package/dist/handlers/projectMembers.js +20 -15
  97. package/dist/handlers/projectMembers.js.map +1 -1
  98. package/dist/handlers/projects.d.ts.map +1 -1
  99. package/dist/handlers/projects.js +10 -3
  100. package/dist/handlers/projects.js.map +1 -1
  101. package/dist/http/api-token.d.ts +17 -0
  102. package/dist/http/api-token.d.ts.map +1 -1
  103. package/dist/http/api-token.js +49 -14
  104. package/dist/http/api-token.js.map +1 -1
  105. package/dist/http/bounded-ttl-cache.d.ts +17 -0
  106. package/dist/http/bounded-ttl-cache.d.ts.map +1 -0
  107. package/dist/http/bounded-ttl-cache.js +58 -0
  108. package/dist/http/bounded-ttl-cache.js.map +1 -0
  109. package/dist/http/csrf.d.ts.map +1 -1
  110. package/dist/http/csrf.js +4 -2
  111. package/dist/http/csrf.js.map +1 -1
  112. package/dist/http/index.d.ts +3 -1
  113. package/dist/http/index.d.ts.map +1 -1
  114. package/dist/http/index.js +3 -1
  115. package/dist/http/index.js.map +1 -1
  116. package/dist/http/redirect.d.ts.map +1 -1
  117. package/dist/http/redirect.js +5 -0
  118. package/dist/http/redirect.js.map +1 -1
  119. package/dist/http/session-refresher.d.ts +14 -0
  120. package/dist/http/session-refresher.d.ts.map +1 -0
  121. package/dist/http/session-refresher.js +34 -0
  122. package/dist/http/session-refresher.js.map +1 -0
  123. package/dist/notifications/smtp-provider.d.ts.map +1 -1
  124. package/dist/notifications/smtp-provider.js +13 -6
  125. package/dist/notifications/smtp-provider.js.map +1 -1
  126. package/dist/oauth/index.d.ts +3 -0
  127. package/dist/oauth/index.d.ts.map +1 -1
  128. package/dist/oauth/index.js +14 -8
  129. package/dist/oauth/index.js.map +1 -1
  130. package/dist/organizations/org-asset-service.d.ts +2 -2
  131. package/dist/organizations/org-asset-service.js +2 -2
  132. package/dist/organizations/user-memberships.d.ts.map +1 -1
  133. package/dist/organizations/user-memberships.js +3 -7
  134. package/dist/organizations/user-memberships.js.map +1 -1
  135. package/dist/projects/delete-with-blobs.d.ts +17 -0
  136. package/dist/projects/delete-with-blobs.d.ts.map +1 -0
  137. package/dist/projects/delete-with-blobs.js +36 -0
  138. package/dist/projects/delete-with-blobs.js.map +1 -0
  139. package/dist/projects/index.d.ts +1 -0
  140. package/dist/projects/index.d.ts.map +1 -1
  141. package/dist/projects/index.js +1 -0
  142. package/dist/projects/index.js.map +1 -1
  143. package/package.json +11 -10
@@ -1,10 +1,10 @@
1
1
  /**
2
- * The server half of an OAuth consent screen: which access levels and orgs the
3
- * user may grant, and minting the key in the org they picked.
2
+ * The server half of an OAuth consent screen: which access levels the user may
3
+ * grant, and minting the key.
4
4
  *
5
- * A key is bound to one org at mint. The user's session acts in one org too,
6
- * but they may belong to several, so consent builds a context pinned to the
7
- * picked org rather than trusting the session's.
5
+ * A key is bound to one org at mint, and consent mints only in the session's
6
+ * acting org: the token page lists and revokes keys there alone, so a key
7
+ * minted elsewhere would be live with no way to see or revoke it.
8
8
  */
9
9
  import { type ApiRequest } from '../api/index.js';
10
10
  import { type ConsentChoice, type OAuthScope } from '../oauth/index.js';
@@ -14,24 +14,36 @@ export interface ConsentOrg {
14
14
  name: string;
15
15
  }
16
16
  /**
17
- * The orgs the signed-in user may grant a key with `scopes` in: those they
18
- * belong to and may hold such a key in.
17
+ * The orgs the signed-in user may grant a key with `scopes` in: their acting
18
+ * org, when they may hold such a key there. At most one.
19
19
  */
20
20
  export declare function consentOrgs(req: ApiRequest, scopes: readonly string[]): Promise<ConsentOrg[]>;
21
- export interface ConsentOffer {
22
- /** Narrowest first. Only levels the user may hold in at least one of their orgs. */
23
- choices: ConsentChoice[];
24
- /** Where the widest choice, the one the page preselects, may be granted. */
21
+ export interface ConsentLevel {
22
+ choice: ConsentChoice;
23
+ /** Where this level may be granted. Never empty. */
25
24
  orgs: ConsentOrg[];
26
25
  }
26
+ export interface ConsentOffer {
27
+ /**
28
+ * Narrowest first. Only levels the user may hold in at least one of their
29
+ * orgs; each carries its own orgs, since a narrower level can reach more.
30
+ */
31
+ levels: ConsentLevel[];
32
+ }
27
33
  /**
28
34
  * What a consent page offers for a request's scopes, and what its approval
29
35
  * accepts. Null when the user may grant none of it anywhere.
30
36
  */
31
37
  export declare function consentOffer(req: ApiRequest, scopes: readonly OAuthScope[]): Promise<ConsentOffer | null>;
32
38
  /**
33
- * Mint the key a consent grants, acting in `orgId`. An org the user doesn't
34
- * belong to is refused here, whatever the form said.
39
+ * Mint the key a consent grants, in `orgId`. Anything but the acting org is
40
+ * refused here, whatever the form said.
35
41
  */
36
42
  export declare function mintConsentToken(req: ApiRequest, orgId: string, input: MintApiTokenInput): Promise<MintedApiToken>;
43
+ /**
44
+ * Revoke a consent key whose code was never redeemed, so an abandoned sign-in
45
+ * doesn't leave a live key nobody holds. A used key is kept: its code may have
46
+ * been redeemed on another replica.
47
+ */
48
+ export declare function revokeUnredeemedConsentToken(req: ApiRequest, tokenId: string): Promise<void>;
37
49
  //# sourceMappingURL=oauthConsent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"oauthConsent.d.ts","sourceRoot":"","sources":["../../src/handlers/oauthConsent.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAyC,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGzF,OAAO,EAGN,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAGN,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,MAAM,gBAAgB,CAAC;AAExB,MAAM,WAAW,UAAU;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACb;AAeD;;;GAGG;AACH,wBAAsB,WAAW,CAChC,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,SAAS,MAAM,EAAE,GACvB,OAAO,CAAC,UAAU,EAAE,CAAC,CAWvB;AAED,MAAM,WAAW,YAAY;IAC5B,oFAAoF;IACpF,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,4EAA4E;IAC5E,IAAI,EAAE,UAAU,EAAE,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAsB,YAAY,CACjC,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,SAAS,UAAU,EAAE,GAC3B,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAU9B;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,iBAAiB,GACtB,OAAO,CAAC,cAAc,CAAC,CASzB"}
1
+ {"version":3,"file":"oauthConsent.d.ts","sourceRoot":"","sources":["../../src/handlers/oauthConsent.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAyC,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGzF,OAAO,EAGN,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAGN,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,MAAM,gBAAgB,CAAC;AAExB,MAAM,WAAW,UAAU;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACb;AAeD;;;GAGG;AACH,wBAAsB,WAAW,CAChC,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,SAAS,MAAM,EAAE,GACvB,OAAO,CAAC,UAAU,EAAE,CAAC,CAavB;AAED,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,aAAa,CAAC;IACtB,oDAAoD;IACpD,IAAI,EAAE,UAAU,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC5B;;;OAGG;IACH,MAAM,EAAE,YAAY,EAAE,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAsB,YAAY,CACjC,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,SAAS,UAAU,EAAE,GAC3B,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAS9B;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,iBAAiB,GACtB,OAAO,CAAC,cAAc,CAAC,CAgBzB;AAED;;;;GAIG;AACH,wBAAsB,4BAA4B,CACjD,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAOf"}
@@ -1,10 +1,10 @@
1
1
  /**
2
- * The server half of an OAuth consent screen: which access levels and orgs the
3
- * user may grant, and minting the key in the org they picked.
2
+ * The server half of an OAuth consent screen: which access levels the user may
3
+ * grant, and minting the key.
4
4
  *
5
- * A key is bound to one org at mint. The user's session acts in one org too,
6
- * but they may belong to several, so consent builds a context pinned to the
7
- * picked org rather than trusting the session's.
5
+ * A key is bound to one org at mint, and consent mints only in the session's
6
+ * acting org: the token page lists and revokes keys there alone, so a key
7
+ * minted elsewhere would be live with no way to see or revoke it.
8
8
  */
9
9
  import { apiError, ApiErrorCode, requireCaller } from '../api/index.js';
10
10
  import { buildRequestContext } from '../http/request-context.js';
@@ -21,12 +21,12 @@ async function contextIn(req, member) {
21
21
  return { ...pinned, adapterContext: ctx.adapterContext };
22
22
  }
23
23
  /**
24
- * The orgs the signed-in user may grant a key with `scopes` in: those they
25
- * belong to and may hold such a key in.
24
+ * The orgs the signed-in user may grant a key with `scopes` in: their acting
25
+ * org, when they may hold such a key there. At most one.
26
26
  */
27
27
  export async function consentOrgs(req, scopes) {
28
28
  const { ctx } = requireCaller(req);
29
- const memberships = await listUserMemberships(req.deps.orgs, ctx.userId);
29
+ const memberships = (await listUserMemberships(req.deps.orgs, ctx.userId)).filter(({ org }) => org.id === ctx.actingOrgId);
30
30
  const allowed = await Promise.all(memberships.map(async ({ member }) => mayHoldApiTokens(req.deps, await contextIn(req, member), scopes)));
31
31
  return memberships
32
32
  .filter((_, i) => allowed[i])
@@ -42,16 +42,17 @@ export async function consentOffer(req, scopes) {
42
42
  orgs: await consentOrgs(req, apiScopesFor(choice.scopes))
43
43
  })));
44
44
  const offered = levels.filter((l) => l.orgs.length > 0);
45
- if (!offered.length)
46
- return null;
47
- return { choices: offered.map((l) => l.choice), orgs: offered[offered.length - 1].orgs };
45
+ return offered.length ? { levels: offered } : null;
48
46
  }
49
47
  /**
50
- * Mint the key a consent grants, acting in `orgId`. An org the user doesn't
51
- * belong to is refused here, whatever the form said.
48
+ * Mint the key a consent grants, in `orgId`. Anything but the acting org is
49
+ * refused here, whatever the form said.
52
50
  */
53
51
  export async function mintConsentToken(req, orgId, input) {
54
52
  const { ctx } = requireCaller(req);
53
+ if (orgId !== ctx.actingOrgId) {
54
+ apiError(403, ApiErrorCode.FORBIDDEN, 'Apps can only be connected to your current organization.');
55
+ }
55
56
  // Matched against the user's own memberships, so the posted id never reaches a store query.
56
57
  const memberships = await listUserMemberships(req.deps.orgs, ctx.userId);
57
58
  const picked = memberships.find(({ org }) => org.id === orgId);
@@ -60,4 +61,19 @@ export async function mintConsentToken(req, orgId, input) {
60
61
  }
61
62
  return mintApiToken({ ...req, ctx: await contextIn(req, picked.member) }, input);
62
63
  }
64
+ /**
65
+ * Revoke a consent key whose code was never redeemed, so an abandoned sign-in
66
+ * doesn't leave a live key nobody holds. A used key is kept: its code may have
67
+ * been redeemed on another replica.
68
+ */
69
+ export async function revokeUnredeemedConsentToken(req, tokenId) {
70
+ const store = req.deps.data.apiTokens;
71
+ if (!store)
72
+ return;
73
+ const { ctx } = requireCaller(req);
74
+ const token = await store.get(ctx, tokenId);
75
+ if (!token || token.revokedAt || token.lastUsedAt)
76
+ return;
77
+ await store.revoke(ctx, tokenId, 'owner');
78
+ }
63
79
  //# sourceMappingURL=oauthConsent.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"oauthConsent.js","sourceRoot":"","sources":["../../src/handlers/oauthConsent.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAmB,MAAM,iBAAiB,CAAC;AACzF,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,EACN,YAAY,EACZ,cAAc,EAGd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,gBAAgB,EAChB,YAAY,EAGZ,MAAM,gBAAgB,CAAC;AAOxB,KAAK,UAAU,SAAS,CAAC,GAAe,EAAE,MAAiB;IAC1D,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;QAClB,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC,SAAS,EAAE,2CAA2C,CAAC,CAAC;IACpF,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CACvC,EAAE,IAAI,EAAE,mBAAmB,EAAE,GAAG,CAAC,mBAAmB,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EACxF,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CACvB,CAAC;IACF,yEAAyE;IACzE,OAAO,EAAE,GAAG,MAAM,EAAE,cAAc,EAAE,GAAG,CAAC,cAAc,EAAE,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,GAAe,EACf,MAAyB;IAEzB,MAAM,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,WAAW,GAAG,MAAM,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzE,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CACpC,gBAAgB,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,CAChE,CACD,CAAC;IACF,OAAO,WAAW;SAChB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;SAC5B,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AACtD,CAAC;AASD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CACjC,GAAe,EACf,MAA6B;IAE7B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QAC7C,MAAM;QACN,IAAI,EAAE,MAAM,WAAW,CAAC,GAAG,EAAE,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;KACzD,CAAC,CAAC,CACH,CAAC;IACF,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACxD,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;AAC3F,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACrC,GAAe,EACf,KAAa,EACb,KAAwB;IAExB,MAAM,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACnC,4FAA4F;IAC5F,MAAM,WAAW,GAAG,MAAM,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzE,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC;IAC/D,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC,SAAS,EAAE,2CAA2C,CAAC,CAAC;IACpF,CAAC;IACD,OAAO,YAAY,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;AAClF,CAAC"}
1
+ {"version":3,"file":"oauthConsent.js","sourceRoot":"","sources":["../../src/handlers/oauthConsent.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"orgAssets.d.ts","sourceRoot":"","sources":["../../src/handlers/orgAssets.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAoD,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAmBpG,eAAO,MAAM,cAAc,EAAE,UAqB5B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,UAO5B,CAAC"}
1
+ {"version":3,"file":"orgAssets.d.ts","sourceRoot":"","sources":["../../src/handlers/orgAssets.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAMN,KAAK,UAAU,EACf,MAAM,iBAAiB,CAAC;AAmBzB,eAAO,MAAM,cAAc,EAAE,UAqB5B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,UAO5B,CAAC"}
@@ -7,7 +7,7 @@
7
7
  * surface: no vector blob is ever stored or served. The allowlist below is the
8
8
  * HTTP gate; the rasterization is the security control.
9
9
  */
10
- import { apiError, ApiErrorCode, noContent, requireUpload } from '../api/index.js';
10
+ import { apiError, ApiErrorCode, noContent, readForm, requireUpload } from '../api/index.js';
11
11
  import { OrgAssetKindSchema } from '@selvajs/platform';
12
12
  import { requireManageOrgMembers, requireActingOrg } from '../access/index.js';
13
13
  import { orgAssetService } from './services.js';
@@ -32,7 +32,7 @@ export const uploadOrgAsset = async (req) => {
32
32
  const org = await req.deps.orgs.getOrg(ctx, orgId);
33
33
  if (!org)
34
34
  apiError(404, ApiErrorCode.NOT_FOUND, 'Organization not found');
35
- const { file } = requireUpload(await req.request.formData(), 'image', {
35
+ const { file } = requireUpload(await readForm(req.request), 'image', {
36
36
  maxBytes: req.deps.uploadLimits.maxImageFileSize,
37
37
  contentTypes: {
38
38
  allowed: ALLOWED_CONTENT_TYPES,
@@ -1 +1 @@
1
- {"version":3,"file":"orgAssets.js","sourceRoot":"","sources":["../../src/handlers/orgAssets.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAmB,MAAM,iBAAiB,CAAC;AACpG,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC;IACrC,WAAW;IACX,YAAY;IACZ,YAAY;IACZ,WAAW;IACX,eAAe;CACf,CAAC,CAAC;AAEH,SAAS,SAAS,CAAC,MAAyB;IAC3C,MAAM,IAAI,GAAG,kBAAkB,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACvD,IAAI,CAAC,IAAI,CAAC,OAAO;QAAE,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC,SAAS,EAAE,uBAAuB,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IAChG,OAAO,IAAI,CAAC,IAAI,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAe,KAAK,EAAE,GAAG,EAAE,EAAE;IACvD,uBAAuB,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE/D,oEAAoE;IACpE,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACnD,IAAI,CAAC,GAAG;QAAE,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC,SAAS,EAAE,wBAAwB,CAAC,CAAC;IAE1E,MAAM,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE;QACrE,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,gBAAgB;QAChD,YAAY,EAAE;YACb,OAAO,EAAE,qBAAqB;YAC9B,OAAO,EAAE,2DAA2D;SACpE;QACD,KAAK,EAAE,OAAO;KACd,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,MAAM,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1F,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC;AAChC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAe,KAAK,EAAE,GAAG,EAAE,EAAE;IACvD,uBAAuB,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE/D,MAAM,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IAC9D,OAAO,SAAS,EAAE,CAAC;AACpB,CAAC,CAAC"}
1
+ {"version":3,"file":"orgAssets.js","sourceRoot":"","sources":["../../src/handlers/orgAssets.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACN,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,aAAa,EAEb,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC;IACrC,WAAW;IACX,YAAY;IACZ,YAAY;IACZ,WAAW;IACX,eAAe;CACf,CAAC,CAAC;AAEH,SAAS,SAAS,CAAC,MAAyB;IAC3C,MAAM,IAAI,GAAG,kBAAkB,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACvD,IAAI,CAAC,IAAI,CAAC,OAAO;QAAE,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC,SAAS,EAAE,uBAAuB,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IAChG,OAAO,IAAI,CAAC,IAAI,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAe,KAAK,EAAE,GAAG,EAAE,EAAE;IACvD,uBAAuB,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE/D,oEAAoE;IACpE,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACnD,IAAI,CAAC,GAAG;QAAE,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC,SAAS,EAAE,wBAAwB,CAAC,CAAC;IAE1E,MAAM,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC,MAAM,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE;QACpE,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,gBAAgB;QAChD,YAAY,EAAE;YACb,OAAO,EAAE,qBAAqB;YAC9B,OAAO,EAAE,2DAA2D;SACpE;QACD,KAAK,EAAE,OAAO;KACd,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,MAAM,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1F,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC;AAChC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAe,KAAK,EAAE,GAAG,EAAE,EAAE;IACvD,uBAAuB,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE/D,MAAM,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IAC9D,OAAO,SAAS,EAAE,CAAC;AACpB,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"orgCompute.d.ts","sourceRoot":"","sources":["../../src/handlers/orgCompute.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAWH,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,iBAAiB,CAAC;AA0B9D,eAAO,MAAM,aAAa,EAAE,UAiC3B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,UA0D9B,CAAC"}
1
+ {"version":3,"file":"orgCompute.d.ts","sourceRoot":"","sources":["../../src/handlers/orgCompute.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAWH,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,iBAAiB,CAAC;AA2B9D,eAAO,MAAM,aAAa,EAAE,UAiC3B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,UA4D9B,CAAC"}
@@ -13,7 +13,7 @@
13
13
  import { apiError, ApiErrorCode, noContent, OrgComputePatchBodySchema, OrgComputeResponseSchema, parseBody, shaped } from '../api/index.js';
14
14
  import { isOrgServer, isPlatformServer, serversVisibleTo } from '@selvajs/platform';
15
15
  import { requireManageOrgCompute, requireActingOrg } from '../access/index.js';
16
- import { evictChangedServers, validateIncomingServers, resolveApiKey, storedKeysById } from '../compute/index.js';
16
+ import { assertStoredKeysReadable, evictChangedServers, validateIncomingServers, resolveApiKey, storedKeysById } from '../compute/index.js';
17
17
  function requireFlag(req) {
18
18
  if (!req.deps.flag('ALLOW_ORG_COMPUTE_OVERRIDE')) {
19
19
  apiError(403, ApiErrorCode.FORBIDDEN, 'Per-org compute override is disabled on this instance (ALLOW_ORG_COMPUTE_OVERRIDE).');
@@ -59,7 +59,9 @@ export const updateOrgCompute = async (req) => {
59
59
  const provider = req.deps.computeServer;
60
60
  // Every key is needed: an unchanged server keeps its stored key across the write.
61
61
  const existing = await provider.getConfig(ctx, { includeApiKeys: true });
62
- const storedKeys = storedKeysById(existing.servers.filter((s) => isOrgServer(s) && s.ownerOrgId === orgId));
62
+ const orgServers = existing.servers.filter((s) => isOrgServer(s) && s.ownerOrgId === orgId);
63
+ assertStoredKeysReadable(incoming.servers, orgServers);
64
+ const storedKeys = storedKeysById(orgServers);
63
65
  const next = incoming.servers.map((s) => ({
64
66
  id: s.id,
65
67
  scope: 'org',
@@ -1 +1 @@
1
- {"version":3,"file":"orgCompute.js","sourceRoot":"","sources":["../../src/handlers/orgCompute.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"orgCompute.js","sourceRoot":"","sources":["../../src/handlers/orgCompute.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"orgMembers.d.ts","sourceRoot":"","sources":["../../src/handlers/orgMembers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAUH,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,iBAAiB,CAAC;AAgG9D;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,UA8D7B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,UA6E7B,CAAC"}
1
+ {"version":3,"file":"orgMembers.d.ts","sourceRoot":"","sources":["../../src/handlers/orgMembers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAUH,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,iBAAiB,CAAC;AAqG9D;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,UA6E7B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,UA+E7B,CAAC"}
@@ -11,9 +11,10 @@
11
11
  * demoting them does.
12
12
  */
13
13
  import { apiError, ApiErrorCode, noContent, parseBody, requireParams, UpdateOrgMemberBodySchema } from '../api/index.js';
14
- import { MEMBER_ASSIGNABLE_PERMISSIONS, ALL_ORG_PERMISSIONS, actorOf, canChangeOrgRole } from '@selvajs/platform';
14
+ import { MEMBER_ASSIGNABLE_PERMISSIONS, ALL_ORG_PERMISSIONS, actorOf, canChangeOrgRole, SYSTEM_CONTEXT } from '@selvajs/platform';
15
15
  import { requireManageOrgMembers, requireActingOrg } from '../access/index.js';
16
16
  import { revokeUserApiTokens } from './apiTokens.js';
17
+ import { serializeOwnerChanges } from './ownerChanges.js';
17
18
  const ROSTER_PAGE_LIMIT = 200;
18
19
  // Runaway guard against an adapter returning a non-advancing cursor. Matches
19
20
  // `listAllOrgMembers`; 100 pages is 20k members, past any real org here.
@@ -68,11 +69,15 @@ async function hasAnotherOwner(req, ctx, orgId, exceptUserId) {
68
69
  *
69
70
  * MUST be called before the removal — afterwards the rows it reads are gone.
70
71
  */
71
- async function findProjectsLosingSoleOwner(req, ctx, orgId, userId) {
72
+ async function findProjectsLosingSoleOwner(req, orgId, userId) {
73
+ // As system: RLS hides private projects from the acting admin, and those are the
74
+ // likeliest to lose their only owner.
72
75
  const projects = req.deps.projects;
73
- const orgProjects = await projects.listProjects(ctx, orgId, { limit: ROSTER_PAGE_LIMIT });
76
+ const orgProjects = await projects.listProjects(SYSTEM_CONTEXT, orgId, {
77
+ limit: ROSTER_PAGE_LIMIT
78
+ });
74
79
  const checks = await Promise.all(orgProjects.items.map(async (project) => {
75
- const members = await projects.listProjectMembers(ctx, project.id, {
80
+ const members = await projects.listProjectMembers(SYSTEM_CONTEXT, project.id, {
76
81
  limit: ROSTER_PAGE_LIMIT
77
82
  });
78
83
  const owners = members.items.filter((m) => m.role === 'owner' && !m.deletedAt);
@@ -96,42 +101,54 @@ export const updateOrgMember = async (req) => {
96
101
  const { ctx, orgId } = requireActingOrg(req, req.params.orgId);
97
102
  const patch = await parseBody(req.request, UpdateOrgMemberBodySchema);
98
103
  const orgs = req.deps.orgs;
99
- const [actorMember, target] = await Promise.all([
100
- orgs.getOrgMember(ctx, orgId, ctx.userId),
101
- orgs.getOrgMember(ctx, orgId, userId)
102
- ]);
103
- if (!target)
104
- apiError(404, ApiErrorCode.NOT_FOUND, 'Member not found in this organization.');
105
- if (!actorMember) {
106
- apiError(403, ApiErrorCode.FORBIDDEN, 'You are not a member of this organization.');
107
- }
108
- if (patch.role !== undefined && patch.role !== target.role) {
109
- // Gated on both the role being granted and the one being taken away —
110
- // demoting an owner is an owner-only act even though `member` is not.
111
- if (!canChangeOrgRole({ actorMember, role: patch.role }) ||
112
- !canChangeOrgRole({ actorMember, role: target.role })) {
113
- apiError(403, ApiErrorCode.FORBIDDEN, 'Only the org owner can change roles.');
104
+ return serializeOwnerChanges(orgId, async () => {
105
+ const [actorMember, target] = await Promise.all([
106
+ orgs.getOrgMember(ctx, orgId, ctx.userId),
107
+ orgs.getOrgMember(ctx, orgId, userId)
108
+ ]);
109
+ if (!target)
110
+ apiError(404, ApiErrorCode.NOT_FOUND, 'Member not found in this organization.');
111
+ if (!actorMember) {
112
+ apiError(403, ApiErrorCode.FORBIDDEN, 'You are not a member of this organization.');
114
113
  }
115
- if (target.role === 'owner' &&
116
- patch.role !== 'owner' &&
117
- !(await hasAnotherOwner(req, ctx, orgId, target.userId))) {
118
- apiError(409, ApiErrorCode.CONFLICT, 'Cannot demote the sole owner of this organization. Promote another member to owner first.');
114
+ const roleChange = patch.role !== undefined && patch.role !== target.role;
115
+ if (roleChange) {
116
+ // Gated on both the role being granted and the one being taken away —
117
+ // demoting an owner is an owner-only act even though `member` is not.
118
+ if (!canChangeOrgRole({ actorMember, role: patch.role }) ||
119
+ !canChangeOrgRole({ actorMember, role: target.role })) {
120
+ apiError(403, ApiErrorCode.FORBIDDEN, 'Only the org owner can change roles.');
121
+ }
122
+ if (target.role === 'owner' &&
123
+ patch.role !== 'owner' &&
124
+ !(await hasAnotherOwner(req, ctx, orgId, target.userId))) {
125
+ apiError(409, ApiErrorCode.CONFLICT, 'Cannot demote the sole owner of this organization. Promote another member to owner first.');
126
+ }
119
127
  }
120
- await orgs.updateOrgMemberRole(ctx, orgId, userId, patch.role);
121
- }
122
- if (patch.permissions !== undefined) {
123
- // Validate against the role the member will have, not the one they had.
124
- const effectiveRole = patch.role ?? target.role;
125
- const valid = effectiveRole === 'member'
126
- ? new Set(MEMBER_ASSIGNABLE_PERMISSIONS)
127
- : new Set(ALL_ORG_PERMISSIONS);
128
- const invalid = patch.permissions.filter((p) => !valid.has(p));
129
- if (invalid.length > 0) {
130
- apiError(400, ApiErrorCode.VALIDATION_FAILED, `Permissions [${invalid.join(', ')}] cannot be assigned to a ${effectiveRole}.`);
128
+ if (patch.permissions !== undefined) {
129
+ // Emptying an owner's or admin's set demotes them in all but name.
130
+ if (!canChangeOrgRole({ actorMember, role: target.role })) {
131
+ apiError(403, ApiErrorCode.FORBIDDEN, 'Only the org owner can change an owner’s or admin’s permissions.');
132
+ }
133
+ // Validate against the role the member will have, not the one they had.
134
+ const effectiveRole = patch.role ?? target.role;
135
+ const valid = effectiveRole === 'member'
136
+ ? new Set(MEMBER_ASSIGNABLE_PERMISSIONS)
137
+ : new Set(ALL_ORG_PERMISSIONS);
138
+ const invalid = patch.permissions.filter((p) => !valid.has(p));
139
+ if (invalid.length > 0) {
140
+ apiError(400, ApiErrorCode.VALIDATION_FAILED, `Permissions [${invalid.join(', ')}] cannot be assigned to a ${effectiveRole}.`);
141
+ }
131
142
  }
132
- await orgs.updateOrgMemberPermissions(ctx, orgId, userId, patch.permissions);
133
- }
134
- return noContent();
143
+ // Writes only after every check, so a refused permission set can't leave a
144
+ // role change behind.
145
+ if (roleChange)
146
+ await orgs.updateOrgMemberRole(ctx, orgId, userId, patch.role);
147
+ if (patch.permissions !== undefined) {
148
+ await orgs.updateOrgMemberPermissions(ctx, orgId, userId, patch.permissions);
149
+ }
150
+ return noContent();
151
+ });
135
152
  };
136
153
  /**
137
154
  * Remove a member from the org. Owner/admin via `manage_org_members`, same
@@ -143,25 +160,28 @@ export const removeOrgMember = async (req) => {
143
160
  requireManageOrgMembers(req);
144
161
  const { ctx, orgId } = requireActingOrg(req, req.params.orgId);
145
162
  const orgs = req.deps.orgs;
146
- const [actorMember, target] = await Promise.all([
147
- orgs.getOrgMember(ctx, orgId, ctx.userId),
148
- orgs.getOrgMember(ctx, orgId, userId)
149
- ]);
150
- if (!target)
151
- apiError(404, ApiErrorCode.NOT_FOUND, 'Member not found in this organization.');
152
- // Same owner-only gate PATCH applies to demotion. Removing an owner ends
153
- // their role just as demoting them does, so an admin got 403 on the demote
154
- // and 204 on the remove — the harder-to-reverse of the two.
155
- if (!canChangeOrgRole({ actorMember, role: target.role })) {
156
- apiError(403, ApiErrorCode.FORBIDDEN, 'Only the org owner can remove another owner.');
157
- }
158
- if (target.role === 'owner' && !(await hasAnotherOwner(req, ctx, orgId, target.userId))) {
159
- apiError(409, ApiErrorCode.CONFLICT, 'Cannot remove the sole owner of this organization. Promote another member to owner first.');
160
- }
161
- // Must run before the removal: the cascade soft-deletes the very rows this
162
- // reads. Reported, not blocked — see the docblock on `findProjectsLosingSoleOwner`.
163
- const orphaned = await findProjectsLosingSoleOwner(req, ctx, orgId, userId);
164
- await orgs.removeOrgMember(ctx, orgId, userId);
163
+ const orphaned = await serializeOwnerChanges(orgId, async () => {
164
+ const [actorMember, target] = await Promise.all([
165
+ orgs.getOrgMember(ctx, orgId, ctx.userId),
166
+ orgs.getOrgMember(ctx, orgId, userId)
167
+ ]);
168
+ if (!target)
169
+ apiError(404, ApiErrorCode.NOT_FOUND, 'Member not found in this organization.');
170
+ // Same owner-only gate PATCH applies to demotion. Removing an owner ends
171
+ // their role just as demoting them does, so an admin got 403 on the demote
172
+ // and 204 on the remove — the harder-to-reverse of the two.
173
+ if (!canChangeOrgRole({ actorMember, role: target.role })) {
174
+ apiError(403, ApiErrorCode.FORBIDDEN, 'Only the org owner can remove another owner.');
175
+ }
176
+ if (target.role === 'owner' && !(await hasAnotherOwner(req, ctx, orgId, target.userId))) {
177
+ apiError(409, ApiErrorCode.CONFLICT, 'Cannot remove the sole owner of this organization. Promote another member to owner first.');
178
+ }
179
+ // Must run before the removal: the cascade soft-deletes the very rows this
180
+ // reads. Reported, not blocked — see the docblock on `findProjectsLosingSoleOwner`.
181
+ const losing = await findProjectsLosingSoleOwner(req, orgId, userId);
182
+ await orgs.removeOrgMember(ctx, orgId, userId);
183
+ return losing;
184
+ });
165
185
  if (orphaned.length > 0) {
166
186
  await req.deps.events.emit({
167
187
  type: 'org_member.removed_orphaning_projects',
@@ -1 +1 @@
1
- {"version":3,"file":"orgMembers.js","sourceRoot":"","sources":["../../src/handlers/orgMembers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"orgMembers.js","sourceRoot":"","sources":["../../src/handlers/orgMembers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Runs one org's or project's member changes one at a time. The sole-owner check
3
+ * reads, then writes: two owners acting on each other at once would each see the
4
+ * other as the survivor and leave none. Per process only; replicas still need an
5
+ * atomic store write to close it.
6
+ */
7
+ export declare function serializeOwnerChanges<T>(id: string, run: () => Promise<T>): Promise<T>;
8
+ //# sourceMappingURL=ownerChanges.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ownerChanges.d.ts","sourceRoot":"","sources":["../../src/handlers/ownerChanges.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAStF"}
@@ -0,0 +1,19 @@
1
+ const ownerChangeQueues = new Map();
2
+ /**
3
+ * Runs one org's or project's member changes one at a time. The sole-owner check
4
+ * reads, then writes: two owners acting on each other at once would each see the
5
+ * other as the survivor and leave none. Per process only; replicas still need an
6
+ * atomic store write to close it.
7
+ */
8
+ export function serializeOwnerChanges(id, run) {
9
+ const previous = ownerChangeQueues.get(id) ?? Promise.resolve();
10
+ const next = previous.catch(() => { }).then(run);
11
+ const tail = next.catch(() => { });
12
+ ownerChangeQueues.set(id, tail);
13
+ void tail.then(() => {
14
+ if (ownerChangeQueues.get(id) === tail)
15
+ ownerChangeQueues.delete(id);
16
+ });
17
+ return next;
18
+ }
19
+ //# sourceMappingURL=ownerChanges.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ownerChanges.js","sourceRoot":"","sources":["../../src/handlers/ownerChanges.ts"],"names":[],"mappings":"AAAA,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAA4B,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAI,EAAU,EAAE,GAAqB;IACzE,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAChE,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAClC,iBAAiB,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAChC,KAAK,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;QACnB,IAAI,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,IAAI;YAAE,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACb,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"projectMembers.d.ts","sourceRoot":"","sources":["../../src/handlers/projectMembers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAeH,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,iBAAiB,CAAC;AAI9D,eAAO,MAAM,kBAAkB,EAAE,UAMhC,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,UAwB9B,CAAC;AAuCF,eAAO,MAAM,uBAAuB,EAAE,UAmBrC,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,UAejC,CAAC"}
1
+ {"version":3,"file":"projectMembers.d.ts","sourceRoot":"","sources":["../../src/handlers/projectMembers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAeH,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,iBAAiB,CAAC;AAK9D,eAAO,MAAM,kBAAkB,EAAE,UAMhC,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,UAwB9B,CAAC;AAuCF,eAAO,MAAM,uBAAuB,EAAE,UAqBrC,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,UAiBjC,CAAC"}
@@ -10,6 +10,7 @@
10
10
  import { AddProjectMemberBodySchema, apiError, ApiErrorCode, collection, created, noContent, parseBody, parseListOptions, requireCaller, requireParams, UpdateProjectMemberBodySchema } from '../api/index.js';
11
11
  import { checkOwnerRemoval } from '@selvajs/platform';
12
12
  import { requireCanManage, requireTargetIsOrgMember } from '../access/index.js';
13
+ import { serializeOwnerChanges } from './ownerChanges.js';
13
14
  export const listProjectMembers = async (req) => {
14
15
  const { id } = requireParams(req.params, 'id');
15
16
  const { ctx } = requireCaller(req);
@@ -69,27 +70,31 @@ export const updateProjectMemberRole = async (req) => {
69
70
  // it runs the same guard DELETE does. Without this a sole owner can PATCH
70
71
  // themselves to `viewer` and lock the project — `canManage`,
71
72
  // `canEditProjectSettings` and `canEdit` all go false at once.
72
- if (role !== 'owner') {
73
- const target = await req.deps.projects.getProjectMember(ctx, id, userId);
74
- if (target?.role === 'owner') {
75
- await assertOwnerRemovable(req, id, target, 'demote');
73
+ return serializeOwnerChanges(id, async () => {
74
+ if (role !== 'owner') {
75
+ const target = await req.deps.projects.getProjectMember(ctx, id, userId);
76
+ if (target?.role === 'owner') {
77
+ await assertOwnerRemovable(req, id, target, 'demote');
78
+ }
76
79
  }
77
- }
78
- await req.deps.projects.updateProjectMemberRole(ctx, id, userId, role);
79
- return noContent();
80
+ await req.deps.projects.updateProjectMemberRole(ctx, id, userId, role);
81
+ return noContent();
82
+ });
80
83
  };
81
84
  export const removeProjectMember = async (req) => {
82
85
  const { id, userId } = requireParams(req.params, 'id', 'userId');
83
86
  const { ctx } = requireCaller(req);
84
87
  await requireCanManage(req, id, 'members');
85
- const target = await req.deps.projects.getProjectMember(ctx, id, userId);
86
- // Idempotent: already gone, or never there.
87
- if (!target)
88
+ return serializeOwnerChanges(id, async () => {
89
+ const target = await req.deps.projects.getProjectMember(ctx, id, userId);
90
+ // Idempotent: already gone, or never there.
91
+ if (!target)
92
+ return noContent();
93
+ if (target.role === 'owner') {
94
+ await assertOwnerRemovable(req, id, target, 'remove');
95
+ }
96
+ await req.deps.projects.removeProjectMember(ctx, id, userId);
88
97
  return noContent();
89
- if (target.role === 'owner') {
90
- await assertOwnerRemovable(req, id, target, 'remove');
91
- }
92
- await req.deps.projects.removeProjectMember(ctx, id, userId);
93
- return noContent();
98
+ });
94
99
  };
95
100
  //# sourceMappingURL=projectMembers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"projectMembers.js","sourceRoot":"","sources":["../../src/handlers/projectMembers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"projectMembers.js","sourceRoot":"","sources":["../../src/handlers/projectMembers.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/handlers/projects.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAYN,KAAK,UAAU,EACf,MAAM,iBAAiB,CAAC;AAyBzB;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,UAgC1B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,UAiD3B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,UAmCxB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,UAuE3B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,UAO3B,CAAC"}
1
+ {"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/handlers/projects.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAYN,KAAK,UAAU,EACf,MAAM,iBAAiB,CAAC;AAyBzB;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,UAgC1B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,UAiD3B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,UAmCxB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,UAyE3B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,UAe3B,CAAC"}