@stigmer/server 3.15.2 → 3.15.3-dev.20260914121148

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 (217) hide show
  1. package/dist/boot/compose.d.ts.map +1 -1
  2. package/dist/boot/compose.js +103 -9
  3. package/dist/boot/compose.js.map +1 -1
  4. package/dist/domain/iampolicy/access-lists.d.ts +27 -0
  5. package/dist/domain/iampolicy/access-lists.d.ts.map +1 -0
  6. package/dist/domain/iampolicy/access-lists.js +124 -0
  7. package/dist/domain/iampolicy/access-lists.js.map +1 -0
  8. package/dist/domain/iampolicy/constants.d.ts +135 -0
  9. package/dist/domain/iampolicy/constants.d.ts.map +1 -0
  10. package/dist/domain/iampolicy/constants.js +203 -0
  11. package/dist/domain/iampolicy/constants.js.map +1 -0
  12. package/dist/domain/iampolicy/controller.d.ts +29 -0
  13. package/dist/domain/iampolicy/controller.d.ts.map +1 -0
  14. package/dist/domain/iampolicy/controller.js +451 -0
  15. package/dist/domain/iampolicy/controller.js.map +1 -0
  16. package/dist/domain/iampolicy/display-resolver.d.ts +6 -0
  17. package/dist/domain/iampolicy/display-resolver.d.ts.map +1 -0
  18. package/dist/domain/iampolicy/display-resolver.js +90 -0
  19. package/dist/domain/iampolicy/display-resolver.js.map +1 -0
  20. package/dist/domain/iampolicy/grant-path.d.ts +42 -0
  21. package/dist/domain/iampolicy/grant-path.d.ts.map +1 -0
  22. package/dist/domain/iampolicy/grant-path.js +183 -0
  23. package/dist/domain/iampolicy/grant-path.js.map +1 -0
  24. package/dist/domain/iampolicy/grant-scope.d.ts +4 -0
  25. package/dist/domain/iampolicy/grant-scope.d.ts.map +1 -0
  26. package/dist/domain/iampolicy/grant-scope.js +34 -0
  27. package/dist/domain/iampolicy/grant-scope.js.map +1 -0
  28. package/dist/domain/iampolicy/membership.d.ts +111 -0
  29. package/dist/domain/iampolicy/membership.d.ts.map +1 -0
  30. package/dist/domain/iampolicy/membership.js +152 -0
  31. package/dist/domain/iampolicy/membership.js.map +1 -0
  32. package/dist/domain/iampolicy/permissions.d.ts +19 -0
  33. package/dist/domain/iampolicy/permissions.d.ts.map +1 -0
  34. package/dist/domain/iampolicy/permissions.js +27 -0
  35. package/dist/domain/iampolicy/permissions.js.map +1 -0
  36. package/dist/domain/iampolicy/resource-store.d.ts +4 -0
  37. package/dist/domain/iampolicy/resource-store.d.ts.map +1 -0
  38. package/dist/domain/iampolicy/resource-store.js +135 -0
  39. package/dist/domain/iampolicy/resource-store.js.map +1 -0
  40. package/dist/domain/iampolicy/role-lifecycle.d.ts +9 -0
  41. package/dist/domain/iampolicy/role-lifecycle.d.ts.map +1 -0
  42. package/dist/domain/iampolicy/role-lifecycle.js +106 -0
  43. package/dist/domain/iampolicy/role-lifecycle.js.map +1 -0
  44. package/dist/domain/iampolicy/roles.d.ts +11 -0
  45. package/dist/domain/iampolicy/roles.d.ts.map +1 -0
  46. package/dist/domain/iampolicy/roles.js +78 -0
  47. package/dist/domain/iampolicy/roles.js.map +1 -0
  48. package/dist/domain/iampolicy/specs.d.ts +7 -0
  49. package/dist/domain/iampolicy/specs.d.ts.map +1 -0
  50. package/dist/domain/iampolicy/specs.js +45 -0
  51. package/dist/domain/iampolicy/specs.js.map +1 -0
  52. package/dist/domain/iampolicy/steps.d.ts +18 -0
  53. package/dist/domain/iampolicy/steps.d.ts.map +1 -0
  54. package/dist/domain/iampolicy/steps.js +117 -0
  55. package/dist/domain/iampolicy/steps.js.map +1 -0
  56. package/dist/domain/iampolicy/store-contract.d.ts +8 -0
  57. package/dist/domain/iampolicy/store-contract.d.ts.map +1 -0
  58. package/dist/domain/iampolicy/store-contract.js +258 -0
  59. package/dist/domain/iampolicy/store-contract.js.map +1 -0
  60. package/dist/domain/iampolicy/store.d.ts +78 -0
  61. package/dist/domain/iampolicy/store.d.ts.map +1 -0
  62. package/dist/domain/iampolicy/store.js +13 -0
  63. package/dist/domain/iampolicy/store.js.map +1 -0
  64. package/dist/domain/iampolicy/wire-refusals.d.ts +25 -0
  65. package/dist/domain/iampolicy/wire-refusals.d.ts.map +1 -0
  66. package/dist/domain/iampolicy/wire-refusals.js +76 -0
  67. package/dist/domain/iampolicy/wire-refusals.js.map +1 -0
  68. package/dist/domain/identityaccount/constants.d.ts +33 -0
  69. package/dist/domain/identityaccount/constants.d.ts.map +1 -1
  70. package/dist/domain/identityaccount/constants.js +2 -48
  71. package/dist/domain/identityaccount/constants.js.map +1 -1
  72. package/dist/domain/identityaccount/controller.d.ts +8 -1
  73. package/dist/domain/identityaccount/controller.d.ts.map +1 -1
  74. package/dist/domain/identityaccount/controller.js +54 -29
  75. package/dist/domain/identityaccount/controller.js.map +1 -1
  76. package/dist/domain/identityaccount/operator.d.ts.map +1 -1
  77. package/dist/domain/identityaccount/operator.js +2 -4
  78. package/dist/domain/identityaccount/operator.js.map +1 -1
  79. package/dist/domain/identityaccount/provisioning.d.ts +20 -1
  80. package/dist/domain/identityaccount/provisioning.d.ts.map +1 -1
  81. package/dist/domain/identityaccount/provisioning.js +17 -3
  82. package/dist/domain/identityaccount/provisioning.js.map +1 -1
  83. package/dist/domain/identityaccount/resolve.d.ts +23 -0
  84. package/dist/domain/identityaccount/resolve.d.ts.map +1 -1
  85. package/dist/domain/identityaccount/resolve.js +17 -0
  86. package/dist/domain/identityaccount/resolve.js.map +1 -1
  87. package/dist/domain/identityaccount/store-contract.d.ts +4 -18
  88. package/dist/domain/identityaccount/store-contract.d.ts.map +1 -1
  89. package/dist/domain/identityaccount/store-contract.js +12 -47
  90. package/dist/domain/identityaccount/store-contract.js.map +1 -1
  91. package/dist/extensions/authorization-queries.d.ts +81 -0
  92. package/dist/extensions/authorization-queries.d.ts.map +1 -0
  93. package/dist/extensions/authorization-queries.js +2 -0
  94. package/dist/extensions/authorization-queries.js.map +1 -0
  95. package/dist/extensions/drivers.d.ts +49 -2
  96. package/dist/extensions/drivers.d.ts.map +1 -1
  97. package/dist/extensions/identity.d.ts +14 -0
  98. package/dist/extensions/identity.d.ts.map +1 -1
  99. package/dist/extensions/identity.js +18 -1
  100. package/dist/extensions/identity.js.map +1 -1
  101. package/dist/extensions/list-read-scope.d.ts +41 -4
  102. package/dist/extensions/list-read-scope.d.ts.map +1 -1
  103. package/dist/extensions/list-read-scope.js +44 -7
  104. package/dist/extensions/list-read-scope.js.map +1 -1
  105. package/dist/extensions/policy-grant-scope.d.ts +50 -0
  106. package/dist/extensions/policy-grant-scope.d.ts.map +1 -0
  107. package/dist/extensions/policy-grant-scope.js +2 -0
  108. package/dist/extensions/policy-grant-scope.js.map +1 -0
  109. package/dist/extensions/registry.d.ts +23 -1
  110. package/dist/extensions/registry.d.ts.map +1 -1
  111. package/dist/extensions/registry.js +30 -0
  112. package/dist/extensions/registry.js.map +1 -1
  113. package/dist/extensions/resource-authorization.d.ts +63 -0
  114. package/dist/extensions/resource-authorization.d.ts.map +1 -1
  115. package/dist/index.d.ts +7 -1
  116. package/dist/index.d.ts.map +1 -1
  117. package/dist/index.js +2 -0
  118. package/dist/index.js.map +1 -1
  119. package/dist/pipeline/apiresource-meta.d.ts +77 -1
  120. package/dist/pipeline/apiresource-meta.d.ts.map +1 -1
  121. package/dist/pipeline/apiresource-meta.js +183 -1
  122. package/dist/pipeline/apiresource-meta.js.map +1 -1
  123. package/dist/pipeline/interceptors/auth.d.ts +12 -0
  124. package/dist/pipeline/interceptors/auth.d.ts.map +1 -1
  125. package/dist/pipeline/interceptors/auth.js +13 -1
  126. package/dist/pipeline/interceptors/auth.js.map +1 -1
  127. package/dist/pipeline/steps/authorization-tuples.d.ts.map +1 -1
  128. package/dist/pipeline/steps/authorization-tuples.js +7 -26
  129. package/dist/pipeline/steps/authorization-tuples.js.map +1 -1
  130. package/dist/pipeline/steps/authorize.d.ts +20 -5
  131. package/dist/pipeline/steps/authorize.d.ts.map +1 -1
  132. package/dist/pipeline/steps/authorize.js +37 -17
  133. package/dist/pipeline/steps/authorize.js.map +1 -1
  134. package/dist/pipeline/steps/defaults.d.ts +10 -0
  135. package/dist/pipeline/steps/defaults.d.ts.map +1 -1
  136. package/dist/pipeline/steps/defaults.js +39 -0
  137. package/dist/pipeline/steps/defaults.js.map +1 -1
  138. package/dist/pipeline/steps/shapes.d.ts +18 -0
  139. package/dist/pipeline/steps/shapes.d.ts.map +1 -1
  140. package/dist/pipeline/steps/shapes.js +29 -0
  141. package/dist/pipeline/steps/shapes.js.map +1 -1
  142. package/dist/store/port-contract.d.ts +61 -0
  143. package/dist/store/port-contract.d.ts.map +1 -0
  144. package/dist/store/port-contract.js +67 -0
  145. package/dist/store/port-contract.js.map +1 -0
  146. package/package.json +4 -4
  147. package/src/boot/compose.ts +107 -10
  148. package/src/domain/iampolicy/__tests__/access-lists.test.ts +238 -0
  149. package/src/domain/iampolicy/__tests__/constants.test.ts +388 -0
  150. package/src/domain/iampolicy/__tests__/controller.test.ts +960 -0
  151. package/src/domain/iampolicy/__tests__/display-resolver.test.ts +138 -0
  152. package/src/domain/iampolicy/__tests__/grant-path.test.ts +474 -0
  153. package/src/domain/iampolicy/__tests__/grant-scope.test.ts +61 -0
  154. package/src/domain/iampolicy/__tests__/iampolicy.test.ts +532 -0
  155. package/src/domain/iampolicy/__tests__/membership.test.ts +447 -0
  156. package/src/domain/iampolicy/__tests__/permissions.test.ts +41 -0
  157. package/src/domain/iampolicy/__tests__/resource-store.test.ts +165 -0
  158. package/src/domain/iampolicy/__tests__/role-lifecycle.test.ts +361 -0
  159. package/src/domain/iampolicy/__tests__/roles.test.ts +53 -0
  160. package/src/domain/iampolicy/__tests__/specs.test.ts +41 -0
  161. package/src/domain/iampolicy/__tests__/steps.test.ts +278 -0
  162. package/src/domain/iampolicy/__tests__/support.ts +195 -0
  163. package/src/domain/iampolicy/__tests__/wire-refusals.test.ts +117 -0
  164. package/src/domain/iampolicy/access-lists.ts +191 -0
  165. package/src/domain/iampolicy/constants.ts +243 -0
  166. package/src/domain/iampolicy/controller.ts +798 -0
  167. package/src/domain/iampolicy/display-resolver.ts +123 -0
  168. package/src/domain/iampolicy/grant-path.ts +270 -0
  169. package/src/domain/iampolicy/grant-scope.ts +36 -0
  170. package/src/domain/iampolicy/membership.ts +298 -0
  171. package/src/domain/iampolicy/permissions.ts +35 -0
  172. package/src/domain/iampolicy/resource-store.ts +186 -0
  173. package/src/domain/iampolicy/role-lifecycle.ts +132 -0
  174. package/src/domain/iampolicy/roles.ts +95 -0
  175. package/src/domain/iampolicy/specs.ts +53 -0
  176. package/src/domain/iampolicy/steps.ts +178 -0
  177. package/src/domain/iampolicy/store-contract.ts +450 -0
  178. package/src/domain/iampolicy/store.ts +103 -0
  179. package/src/domain/iampolicy/wire-refusals.ts +110 -0
  180. package/src/domain/identityaccount/__tests__/provisioning.test.ts +19 -7
  181. package/src/domain/identityaccount/__tests__/resolve.test.ts +113 -2
  182. package/src/domain/identityaccount/constants.ts +16 -31
  183. package/src/domain/identityaccount/controller.ts +65 -35
  184. package/src/domain/identityaccount/operator.ts +5 -5
  185. package/src/domain/identityaccount/provisioning.ts +43 -5
  186. package/src/domain/identityaccount/resolve.ts +43 -0
  187. package/src/domain/identityaccount/store-contract.ts +22 -70
  188. package/src/extensions/__tests__/composed-support.ts +87 -0
  189. package/src/extensions/__tests__/iam-policy-composed.test.ts +373 -0
  190. package/src/extensions/__tests__/iam-policy-points.test.ts +169 -0
  191. package/src/extensions/__tests__/identity-account-composed.test.ts +12 -78
  192. package/src/extensions/__tests__/identity.test.ts +62 -0
  193. package/src/extensions/__tests__/list-read-scope.test.ts +138 -0
  194. package/src/extensions/__tests__/tier-truthfulness.test.ts +8 -0
  195. package/src/extensions/authorization-queries.ts +97 -0
  196. package/src/extensions/drivers.ts +49 -2
  197. package/src/extensions/identity.ts +21 -0
  198. package/src/extensions/list-read-scope.ts +87 -9
  199. package/src/extensions/policy-grant-scope.ts +50 -0
  200. package/src/extensions/registry.ts +62 -1
  201. package/src/extensions/resource-authorization.ts +65 -0
  202. package/src/index.ts +20 -0
  203. package/src/pipeline/__tests__/grantable-roles-for.test.ts +87 -0
  204. package/src/pipeline/__tests__/inherited-authorization-parent.test.ts +51 -0
  205. package/src/pipeline/__tests__/kind-by-enum-name.test.ts +107 -0
  206. package/src/pipeline/__tests__/kind-served-by-edition.test.ts +107 -0
  207. package/src/pipeline/apiresource-meta.ts +218 -1
  208. package/src/pipeline/interceptors/auth.ts +14 -1
  209. package/src/pipeline/steps/__tests__/authorize-annotation-completeness.test.ts +73 -3
  210. package/src/pipeline/steps/__tests__/authorize.test.ts +134 -9
  211. package/src/pipeline/steps/__tests__/derived-id.test.ts +49 -0
  212. package/src/pipeline/steps/authorization-tuples.ts +7 -28
  213. package/src/pipeline/steps/authorize.ts +46 -21
  214. package/src/pipeline/steps/defaults.ts +42 -0
  215. package/src/pipeline/steps/shapes.ts +31 -0
  216. package/src/store/__tests__/port-contract.test.ts +123 -0
  217. package/src/store/port-contract.ts +102 -0
@@ -0,0 +1,183 @@
1
+ /**
2
+ * The ONE grant and revoke path of the IamPolicy domain (20260913.01,
3
+ * T01_0_plan.md §3a; T01_1_review.md Q-OR-1), moved from the cloud's
4
+ * iam/policy/service.ts into open source so every edition writes and
5
+ * deletes a policy row the same way. Its callers: the IamPolicy command
6
+ * controller (user grants and the three system RPCs), the built-in role
7
+ * lifecycle (the organization creator's `owner` row; cleanup on delete)
8
+ * and the membership rules (first-sign-in roles). Nothing else builds,
9
+ * saves or deletes a policy row; a composition reaches this path as
10
+ * in-process RPCs, never through an exported constructor.
11
+ *
12
+ * The two cloud#425 ordering invariants live here, nowhere else:
13
+ * CREATE: row before tuple — a crash between the two leaves
14
+ * row-without-tuple (granted on paper, denied in practice), healed by
15
+ * the caller's natural retry (the tuple write deliberately runs on
16
+ * duplicates too — the inline heal) or the boot backfill.
17
+ * DELETE: tuple before row — a crash leaves row+tuple (revoke failed,
18
+ * retry works); the reverse order was the fail-open incident class
19
+ * ("revoke access" silently becoming "keep access forever").
20
+ * "Tuple" here is whatever the composed ResourceAuthorizationLifecycle does
21
+ * in `onPolicyGranted` and `onPolicyRevoked`; with none composed, or one
22
+ * without the two optional hooks, the path writes rows and notifies
23
+ * nothing (the OSS posture: rows are the record).
24
+ *
25
+ * The row for a triple is found BY TRIPLE, never by derived id. Open
26
+ * source's rows carry the derived id (constants.ts policyIdFor), so the
27
+ * two lookups would agree here; the cloud's Java-era rows carry random
28
+ * `iamp_<ulid>` ids and must revoke and deduplicate through this same
29
+ * code, so `findByTriple` (the pair's rows filtered by relation) is the
30
+ * one definition of "the row for this triple" and `findById` serves the
31
+ * `get` RPC alone. On the OSS adapter that read is one scan of the kind
32
+ * (resource-store.ts); §4 measures it.
33
+ *
34
+ * The path is the one writer, so it refuses before it writes (Q-S2-1;
35
+ * slice 1 ruling 2): before any read, write or hook, `grant` and
36
+ * `revokeBySpec` run the domain's wire refusals (wire-refusals.ts — a spec
37
+ * whose resource or principal kind is not an ApiResourceKind member name,
38
+ * or whose fields hold a canonical-text delimiter, is INVALID_ARGUMENT
39
+ * with the pinned copy; slice 5 made that module the one home of the rule
40
+ * the controller and the ValidateGrantableRole step share). The
41
+ * controller refuses the same kinds BEFORE position 1 (Q-S6-1), so a wire
42
+ * caller never reaches this check; it stands for the callers that enter
43
+ * here without the controller — the built-in lifecycle and the membership
44
+ * rules — and is what keeps a garbage row out of the store and a garbage
45
+ * spec away from a composition's tuple delete from every door.
46
+ * `cleanupResource` and `revokeOrgAccess` take refs and ids their callers
47
+ * read from rows, so they do not refuse.
48
+ *
49
+ * The row this path builds: the proto's apiVersion const and kind, the
50
+ * derived id, the spec as given, and the caller's audit stamp through the
51
+ * platform's one stamper (setAuditFieldsForCreate) — the cloud's
52
+ * `buildNewPolicy` stamped neither org nor creator; this path stamps the
53
+ * creator and, like the cloud, no `metadata.org`, because a policy may
54
+ * span organizations and none owns it.
55
+ */
56
+ import { create } from "@bufbuild/protobuf";
57
+ import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
58
+ import { ApiResourceMetadataSchema } from "@stigmer/protos/ai/stigmer/commons/apiresource/metadata_pb";
59
+ import { IamPolicySchema } from "@stigmer/protos/ai/stigmer/iam/iampolicy/v1/api_pb";
60
+ import { kindEnumName } from "../../pipeline/apiresource-meta.js";
61
+ import { setAuditFieldsForCreate } from "../../pipeline/steps/defaults.js";
62
+ import { IAM_POLICY_API_VERSION, IAM_POLICY_KIND, policyIdFor, } from "./constants.js";
63
+ import { DuplicatePolicyError } from "./store.js";
64
+ import { refsOf, requireWellFormedTriple } from "./wire-refusals.js";
65
+ export function newIamPolicyGrantPath(deps) {
66
+ const { policies, lifecycle, logger } = deps;
67
+ /** The row holding this exact triple — the pair's rows, filtered by relation. */
68
+ async function findByTriple(spec) {
69
+ const { principal, resource } = refsOf(spec);
70
+ const onPair = await policies.findByPrincipalAndResource(principal.kind, principal.id, resource.kind, resource.id);
71
+ return onPair.find((policy) => policy.spec !== undefined &&
72
+ policy.spec.relation === spec.relation &&
73
+ policy.spec.principal?.relation === principal.relation);
74
+ }
75
+ /** The revoke order for one row: the hook, then the delete. */
76
+ async function revokeRow(policy) {
77
+ const spec = policy.spec;
78
+ if (spec === undefined) {
79
+ throw new Error(`policy ${policy.metadata?.id ?? "?"} has no spec — corrupt row`);
80
+ }
81
+ await lifecycle?.onPolicyRevoked?.({ spec, policy });
82
+ const id = policy.metadata?.id ?? "";
83
+ await policies.deleteById(id);
84
+ logger.info("iam policy revoked", fieldsOf(id, spec));
85
+ }
86
+ return {
87
+ async grant(spec, caller) {
88
+ requireWellFormedTriple(spec);
89
+ let policy = await findByTriple(spec);
90
+ let duplicate = policy !== undefined;
91
+ if (policy === undefined) {
92
+ const fresh = buildRow(spec, caller);
93
+ try {
94
+ await policies.save(fresh);
95
+ policy = fresh;
96
+ logger.info("iam policy granted", fieldsOf(policyIdFor(spec), spec));
97
+ }
98
+ catch (error) {
99
+ if (!(error instanceof DuplicatePolicyError)) {
100
+ throw error;
101
+ }
102
+ // Lost the race to another writer of the same triple: the
103
+ // winner's row is the grant, exactly as if it had been found
104
+ // above. A winner that cannot be read back means the refusal
105
+ // was not a race — propagate it.
106
+ const winner = await findByTriple(spec);
107
+ if (winner === undefined) {
108
+ throw error;
109
+ }
110
+ policy = winner;
111
+ duplicate = true;
112
+ }
113
+ }
114
+ if (duplicate) {
115
+ logger.debug("iam policy already held", fieldsOf(policy.metadata?.id ?? "", spec));
116
+ }
117
+ // Deliberately unconditional (cloud#425): a duplicate re-grant is the
118
+ // inline heal for a row whose tuple never landed.
119
+ await lifecycle?.onPolicyGranted?.({ policy, duplicate });
120
+ return { policy, duplicate };
121
+ },
122
+ async revokeBySpec(spec) {
123
+ requireWellFormedTriple(spec);
124
+ const existing = await findByTriple(spec);
125
+ if (existing === undefined) {
126
+ // No row: a composition still deletes the bare tuple (one written
127
+ // before the row mirror existed); converges the store either way.
128
+ await lifecycle?.onPolicyRevoked?.({ spec, policy: undefined });
129
+ return undefined;
130
+ }
131
+ await revokeRow(existing);
132
+ return existing;
133
+ },
134
+ async cleanupResource(ref) {
135
+ const asResource = await policies.findByResource(ref.kind, ref.id);
136
+ const asPrincipal = await policies.findByPrincipal(ref.kind, ref.id);
137
+ for (const policy of distinctById([...asResource, ...asPrincipal])) {
138
+ await revokeRow(policy);
139
+ }
140
+ },
141
+ async revokeOrgAccess(identityAccountId, organizationId) {
142
+ const direct = await policies.findByPrincipalAndResource(kindEnumName(ApiResourceKind.identity_account), identityAccountId, kindEnumName(ApiResourceKind.organization), organizationId);
143
+ for (const policy of direct) {
144
+ await revokeRow(policy);
145
+ }
146
+ },
147
+ };
148
+ }
149
+ /** The row for a fresh grant: the contract's identity strings, the derived id, the caller's stamp. */
150
+ function buildRow(spec, caller) {
151
+ const policy = create(IamPolicySchema, {
152
+ apiVersion: IAM_POLICY_API_VERSION,
153
+ kind: IAM_POLICY_KIND,
154
+ metadata: create(ApiResourceMetadataSchema, { id: policyIdFor(spec) }),
155
+ spec,
156
+ });
157
+ setAuditFieldsForCreate(IamPolicySchema, policy, caller);
158
+ return policy;
159
+ }
160
+ /** One row per id, at its first position. */
161
+ function distinctById(policies) {
162
+ const seen = new Set();
163
+ return policies.filter((policy) => {
164
+ const id = policy.metadata?.id ?? "";
165
+ if (seen.has(id)) {
166
+ return false;
167
+ }
168
+ seen.add(id);
169
+ return true;
170
+ });
171
+ }
172
+ /** The structured fields every log line carries — ids and kinds, never a token. */
173
+ function fieldsOf(id, spec) {
174
+ return {
175
+ policyId: id,
176
+ relation: spec.relation,
177
+ principalKind: spec.principal?.kind ?? "",
178
+ principalId: spec.principal?.id ?? "",
179
+ resourceKind: spec.resource?.kind ?? "",
180
+ resourceId: spec.resource?.id ?? "",
181
+ };
182
+ }
183
+ //# sourceMappingURL=grant-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grant-path.js","sourceRoot":"","sources":["../../../src/domain/iampolicy/grant-path.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { PolicyGrantScope } from "../../extensions/policy-grant-scope.js";
2
+ /** The open-source default: organization → its proto roles; every other kind → none. */
3
+ export declare function newOrganizationOnlyGrantScope(): PolicyGrantScope;
4
+ //# sourceMappingURL=grant-scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grant-scope.d.ts","sourceRoot":"","sources":["../../../src/domain/iampolicy/grant-scope.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAG/E,wFAAwF;AACxF,wBAAgB,6BAA6B,IAAI,gBAAgB,CAQhE"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Open source's PolicyGrantScope (20260913.01, T01_1_review.md Q-OR-3 and
3
+ * Q-OR-4): the ORGANIZATION grants the roles its `kind_meta` lists —
4
+ * owner, admin, member, viewer — and no other kind grants anything. This
5
+ * is what lights the console's Members page in every edition while a
6
+ * viewer on one agent, the per-resource grant, stays what the Enterprise
7
+ * and Cloud editions add by composing a wider scope
8
+ * (extensions/policy-grant-scope.ts carries the contract every scope is
9
+ * held to: narrows the proto, total over the enum, synchronous).
10
+ *
11
+ * Installed by the composition root when no unit registers
12
+ * `drivers.policyGrantScope` — the `newPermissiveSingleTeamAuthorizer`
13
+ * shape: the default lives with the domain that defines its semantics and
14
+ * is called at the `??` site, never held by the registry.
15
+ *
16
+ * The organization's roles are READ from the proto through
17
+ * `grantableRolesFor`, not written here: the four words the Members page
18
+ * shows and entry 3's authorizer enforces have one source, and a proto
19
+ * change is the only way to change them (grant-scope.test.ts pins the
20
+ * equality; grantable-roles-for.test.ts pins the four).
21
+ */
22
+ import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
23
+ import { grantableRolesFor } from "../../pipeline/apiresource-meta.js";
24
+ /** The open-source default: organization → its proto roles; every other kind → none. */
25
+ export function newOrganizationOnlyGrantScope() {
26
+ return {
27
+ grantableRoles(kind) {
28
+ return kind === ApiResourceKind.organization
29
+ ? grantableRolesFor(kind)
30
+ : [];
31
+ },
32
+ };
33
+ }
34
+ //# sourceMappingURL=grant-scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grant-scope.js","sourceRoot":"","sources":["../../../src/domain/iampolicy/grant-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,qFAAqF,CAAC;AAGtH,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAEvE,wFAAwF;AACxF,MAAM,UAAU,6BAA6B;IAC3C,OAAO;QACL,cAAc,CAAC,IAAI;YACjB,OAAO,IAAI,KAAK,eAAe,CAAC,YAAY;gBAC1C,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC;gBACzB,CAAC,CAAC,EAAE,CAAC;QACT,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * The open-source membership rules (20260913.01, T01_0_plan.md §3a;
3
+ * T01_1_review.md Q-OR-6b, Q-OR-6c; slice 4 rulings Q-S4-2 to Q-S4-7):
4
+ * how organization roles come to exist on a self-host that has no
5
+ * administrator to grant them. Core code, installed only under the
6
+ * built-in authorization posture (boot/compose.ts `builtInAuthorization`:
7
+ * no unit registered an Authorizer); a composition with its own
8
+ * Authorizer has its own onboarding and never constructs this.
9
+ *
10
+ * Two moments:
11
+ *
12
+ * onAccountCreated(account, caller) — a person's FIRST provisioning, and
13
+ * only that (the identity-account domain's AccountCreatedHook, run by
14
+ * provisionMyAccount on the call whose `created` is true). For every
15
+ * organization the account holds no row on, in this order:
16
+ * 1. `owner` — the organization's creator stamp is this account (its
17
+ * subject or its id): the founder, who founded it
18
+ * idp-shaped before any row existed;
19
+ * 2. `admin` — this account created a blueprint in it (BLUEPRINT_KINDS,
20
+ * constants.ts: the kinds an admin authors; sessions and
21
+ * executions are personal and confer nothing, DD-002
22
+ * rule 2);
23
+ * 3. `admin` — the account's email is the configured operator email
24
+ * (an empty configuration matches nobody);
25
+ * 4. `admin` — the organization has ZERO role rows and no PERSON other
26
+ * than this account created it or any blueprint in it:
27
+ * the fresh install's first caller, and the
28
+ * trusted-local-turned-OIDC laptop whose stamps are all
29
+ * "system". "Zero rows", never "no admin now" — revoking
30
+ * every admin of a bootstrapped organization must not
31
+ * hand it to the next stranger (plan finding 2); and the
32
+ * founder's own stamp counts as a person (Q-S4-7), so a
33
+ * revoked founder's empty organization is not handed
34
+ * over either;
35
+ * 5. `member` — everyone else.
36
+ * Arms 3 and 4 both answer `admin`; 3 is checked first because it is a
37
+ * string compare and 4 reads the organization's rows. `user`-class
38
+ * callers only (Q-OR-6b): a runner, a machine or the in-process class
39
+ * never earns a role. Nothing on an organization the account already
40
+ * holds a row on, so a run that faulted midway converges on the next.
41
+ *
42
+ * ensureOperatorOwnership(operator) — the trusted-local boot ensure
43
+ * (Q-OR-6c): the laptop's operator becomes `owner` of every organization
44
+ * that has NO owner row. "No owner row", not "no row of this operator"
45
+ * (Q-S4-3): a boot-time write never overrides a human grant recorded
46
+ * under an earlier OIDC life of the same database, and the permissive
47
+ * Authorizer admits the operator regardless. A second boot writes
48
+ * nothing. The row is granted AS the operator — the trusted-local
49
+ * identity shape (empty issuer and token) carrying the account's id,
50
+ * email and name — so its audit actor reads like every other write on
51
+ * that laptop.
52
+ *
53
+ * What a creator stamp is. The rules read `status.audit.spec_audit
54
+ * .created_by.id` off organizations and blueprints. That stamp is the
55
+ * caller's identityId at the time: a provisioned caller's ACCOUNT id, an
56
+ * unprovisioned caller's raw issuer SUBJECT, and — under the trusted-local
57
+ * posture — the operator's EMAIL or the "system" placeholder
58
+ * (pipeline/interceptors/auth.ts trustedLocalIdentityFor). So "mine" is
59
+ * "equals my subject or my id" (an email stamp is nobody's by this rule;
60
+ * the operator is covered by arm 3 and by ensureOperatorOwnership), and a
61
+ * stamp is a PERSON when it is non-empty and not the "system" placeholder
62
+ * (SYSTEM_OPERATOR_IDENTITY_ID, the one home of that word — Q-S4-6). The
63
+ * rules classify stamps by shape and consult no account store (Q-S4-5).
64
+ *
65
+ * Reads. Policy rows through the IamPolicyStore PORT (`policies`, the
66
+ * same instance the grant path writes through) — never around it
67
+ * (Q-S4-5). Organizations and blueprints through the generic Store,
68
+ * decoded with each kind's own schema (CREATOR_SCAN_SCHEMAS; Q-S4-2: the
69
+ * envelope shares its field numbers but each status carries its audit
70
+ * under its own, so no generic decode exists). Cost, measured in the
71
+ * entry's execution record: one scan of each of seven kinds and one row
72
+ * read per organization, once per account creation.
73
+ *
74
+ * The window this design accepts (Q-S4-4). A store fault after the
75
+ * account row persisted fails the request INTERNAL (the controller's
76
+ * mapping) with the account in place; later calls answer `created:
77
+ * false`, so the rules never run again for that person. The writes ride
78
+ * the idempotent grant path, so a partial run leaves only correct rows,
79
+ * and the recovery is an administrator's grant — or, on a fresh install,
80
+ * arm 3 at the operator's own sign-in. An account created through the
81
+ * `create` RPC (the platform's own pipelines, cloud#393) never reaches
82
+ * this hook either: the rules are about a person signing in.
83
+ */
84
+ import type { DescMessage } from "@bufbuild/protobuf";
85
+ import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
86
+ import type { IdentityAccount } from "@stigmer/protos/ai/stigmer/iam/identityaccount/v1/api_pb";
87
+ import type { Store } from "../../store/interface.js";
88
+ import type { AccountCreatedHook } from "../identityaccount/provisioning.js";
89
+ import type { IamPolicyGrantPath } from "./grant-path.js";
90
+ import type { IamPolicyStore } from "./store.js";
91
+ export interface MembershipRulesDeps {
92
+ readonly grantPath: IamPolicyGrantPath;
93
+ /** The port the grant path writes through — read here for "holds a row", "zero rows", "has an owner". */
94
+ readonly policies: IamPolicyStore;
95
+ readonly store: Store;
96
+ /** STIGMER_OPERATOR_EMAIL as the operator seam holds it; "" when unconfigured. */
97
+ readonly operatorEmail: string;
98
+ }
99
+ export interface MembershipRules extends AccountCreatedHook {
100
+ /** The trusted-local boot ensure: `owner` wherever no owner row exists. */
101
+ ensureOperatorOwnership(operator: IdentityAccount): Promise<void>;
102
+ }
103
+ /**
104
+ * The schemas the creator scan decodes with: the organization and every
105
+ * BLUEPRINT_KINDS member. Pinned equal to that set by the domain's tests,
106
+ * so a kind added to the constant without a schema fails loudly instead
107
+ * of being skipped.
108
+ */
109
+ export declare const CREATOR_SCAN_SCHEMAS: ReadonlyMap<ApiResourceKind, DescMessage>;
110
+ export declare function newMembershipRules(deps: MembershipRulesDeps): MembershipRules;
111
+ //# sourceMappingURL=membership.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"membership.d.ts","sourceRoot":"","sources":["../../../src/domain/iampolicy/membership.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkFG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAStD,OAAO,EAAE,eAAe,EAAE,MAAM,qFAAqF,CAAC;AACtH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0DAA0D,CAAC;AAShG,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAE7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAC;IACvC,yGAAyG;IACzG,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,kFAAkF;IAClF,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,eAAgB,SAAQ,kBAAkB;IACzD,2EAA2E;IAC3E,uBAAuB,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnE;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,eAAe,EAAE,WAAW,CASvE,CAAC;AAiBL,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,mBAAmB,GAAG,eAAe,CAuH7E"}
@@ -0,0 +1,152 @@
1
+ import { fromBinary } from "@bufbuild/protobuf";
2
+ import { AgentSchema } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
3
+ import { EnvironmentSchema } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/api_pb";
4
+ import { McpServerSchema } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/api_pb";
5
+ import { ScheduleSchema } from "@stigmer/protos/ai/stigmer/agentic/schedule/v1/api_pb";
6
+ import { SkillSchema } from "@stigmer/protos/ai/stigmer/agentic/skill/v1/api_pb";
7
+ import { WorkflowSchema } from "@stigmer/protos/ai/stigmer/agentic/workflow/v1/api_pb";
8
+ import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
9
+ import { IamRole } from "@stigmer/protos/ai/stigmer/iam/v1/enum_pb";
10
+ import { OrganizationSchema } from "@stigmer/protos/ai/stigmer/tenancy/organization/v1/api_pb";
11
+ import { kindEnumName } from "../../pipeline/apiresource-meta.js";
12
+ import { SYSTEM_OPERATOR_IDENTITY_ID } from "../../pipeline/interceptors/auth.js";
13
+ import { auditOf } from "../../pipeline/steps/defaults.js";
14
+ import { metadataOf } from "../../pipeline/steps/shapes.js";
15
+ import { BLUEPRINT_KINDS } from "./constants.js";
16
+ import { organizationRole, relationOf } from "./specs.js";
17
+ /**
18
+ * The schemas the creator scan decodes with: the organization and every
19
+ * BLUEPRINT_KINDS member. Pinned equal to that set by the domain's tests,
20
+ * so a kind added to the constant without a schema fails loudly instead
21
+ * of being skipped.
22
+ */
23
+ export const CREATOR_SCAN_SCHEMAS = new Map([
24
+ [ApiResourceKind.organization, OrganizationSchema],
25
+ [ApiResourceKind.agent, AgentSchema],
26
+ [ApiResourceKind.workflow, WorkflowSchema],
27
+ [ApiResourceKind.skill, SkillSchema],
28
+ [ApiResourceKind.mcp_server, McpServerSchema],
29
+ [ApiResourceKind.environment, EnvironmentSchema],
30
+ [ApiResourceKind.schedule, ScheduleSchema],
31
+ ]);
32
+ const ORGANIZATION = kindEnumName(ApiResourceKind.organization);
33
+ const IDENTITY_ACCOUNT = kindEnumName(ApiResourceKind.identity_account);
34
+ /** A creator stamp that names a person: non-empty and not the unconfigured laptop's placeholder. */
35
+ function isPersonStamp(stamp) {
36
+ return stamp !== "" && stamp !== SYSTEM_OPERATOR_IDENTITY_ID;
37
+ }
38
+ export function newMembershipRules(deps) {
39
+ const { grantPath, policies, store, operatorEmail } = deps;
40
+ async function scan(kind) {
41
+ const schema = CREATOR_SCAN_SCHEMAS.get(kind);
42
+ if (schema === undefined) {
43
+ throw new Error(`no schema to decode ${kindEnumName(kind)} rows for the creator scan`);
44
+ }
45
+ const rows = await store.listResources(kind);
46
+ return rows.map((bytes) => {
47
+ const resource = fromBinary(schema, bytes);
48
+ const metadata = metadataOf(resource);
49
+ return {
50
+ id: metadata?.id ?? "",
51
+ org: metadata?.org ?? "",
52
+ createdBy: auditOf(schema, resource)?.specAudit?.createdBy?.id ?? "",
53
+ };
54
+ });
55
+ }
56
+ async function scanBlueprints() {
57
+ const scanned = [];
58
+ for (const kind of BLUEPRINT_KINDS) {
59
+ scanned.push(...(await scan(kind)));
60
+ }
61
+ return scanned;
62
+ }
63
+ /** The organizations `accountId` already holds any row on — the idempotency set. */
64
+ async function organizationsHeldBy(accountId) {
65
+ const rows = await policies.findByPrincipal(IDENTITY_ACCOUNT, accountId);
66
+ return new Set(rows
67
+ .filter((row) => row.spec?.resource?.kind === ORGANIZATION)
68
+ .map((row) => row.spec?.resource?.id ?? ""));
69
+ }
70
+ return {
71
+ async onAccountCreated(account, caller) {
72
+ if (caller.callerClass !== "user") {
73
+ return;
74
+ }
75
+ const accountId = account.metadata?.id ?? "";
76
+ if (accountId === "") {
77
+ throw new Error("membership rules: the provisioned account carries no id");
78
+ }
79
+ const organizations = await scan(ApiResourceKind.organization);
80
+ if (organizations.length === 0) {
81
+ return;
82
+ }
83
+ const subject = account.spec?.idpId ?? "";
84
+ const email = account.spec?.email ?? "";
85
+ const isMine = (stamp) => stamp !== "" && (stamp === subject || stamp === accountId);
86
+ const held = await organizationsHeldBy(accountId);
87
+ const blueprints = await scanBlueprints();
88
+ for (const organization of organizations) {
89
+ if (held.has(organization.id)) {
90
+ continue;
91
+ }
92
+ const inOrganization = blueprints.filter((blueprint) => blueprint.org === organization.id);
93
+ let role;
94
+ if (isMine(organization.createdBy)) {
95
+ role = IamRole.owner;
96
+ }
97
+ else if (inOrganization.some((b) => isMine(b.createdBy))) {
98
+ role = IamRole.admin;
99
+ }
100
+ else if (operatorEmail !== "" && email === operatorEmail) {
101
+ role = IamRole.admin;
102
+ }
103
+ else if (![
104
+ organization.createdBy,
105
+ ...inOrganization.map((b) => b.createdBy),
106
+ ].some((stamp) => isPersonStamp(stamp) && !isMine(stamp)) &&
107
+ (await policies.findByResource(ORGANIZATION, organization.id))
108
+ .length === 0) {
109
+ role = IamRole.admin;
110
+ }
111
+ else {
112
+ role = IamRole.member;
113
+ }
114
+ await grantPath.grant(organizationRole(accountId, role, organization.id), caller);
115
+ }
116
+ },
117
+ async ensureOperatorOwnership(operator) {
118
+ const accountId = operator.metadata?.id ?? "";
119
+ if (accountId === "") {
120
+ throw new Error("membership rules: the operator account carries no id");
121
+ }
122
+ const actor = operatorActor(operator, accountId);
123
+ for (const organization of await scan(ApiResourceKind.organization)) {
124
+ const owners = await policies.findByResourceWithRelations(ORGANIZATION, organization.id, [relationOf(IamRole.owner)]);
125
+ if (owners.length > 0) {
126
+ continue;
127
+ }
128
+ await grantPath.grant(organizationRole(accountId, IamRole.owner, organization.id), actor);
129
+ }
130
+ },
131
+ };
132
+ }
133
+ /**
134
+ * The operator acting as its account: the trusted-local identity shape
135
+ * (pipeline/interceptors/auth.ts trustedLocalIdentityFor — no issuer, no
136
+ * token; email and display name only when known) with the account id as
137
+ * the principal, so the row's audit actor is the account, named the way
138
+ * every other trusted-local write names it.
139
+ */
140
+ function operatorActor(operator, accountId) {
141
+ const email = operator.spec?.email ?? "";
142
+ const displayName = operator.metadata?.name ?? "";
143
+ return {
144
+ identityId: accountId,
145
+ callerClass: "user",
146
+ issuer: "",
147
+ rawToken: "",
148
+ ...(email !== "" ? { email } : {}),
149
+ ...(displayName !== "" ? { displayName } : {}),
150
+ };
151
+ }
152
+ //# sourceMappingURL=membership.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"membership.js","sourceRoot":"","sources":["../../../src/domain/iampolicy/membership.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The permission vocabulary as the wire spells it (20260913.01 slice 5,
3
+ * Q-S5-3): `checkMyPermission` carries its `relation` as a string — the
4
+ * FGA relation name, which is the `IamPermission` member name — while the
5
+ * composed Authorizer's `AuthzCheck` carries the enum. This is the one
6
+ * read from the first spelling to the second. A relation that names no
7
+ * permission is the caller's mistake (INVALID_ARGUMENT in the controller),
8
+ * never a permission nobody holds: the console asks with the ten strings
9
+ * `IamPermission` lists (claim check C4) and a typo should be heard.
10
+ *
11
+ * A Map over the descriptor's values, never the TS enum's reverse index
12
+ * (the `kindsByEnumName` doctrine in pipeline/apiresource-meta.ts): a
13
+ * prototype key or a number spelled as text must resolve to nothing. The
14
+ * zero value `unspecified` is not a permission and is left out.
15
+ */
16
+ import { IamPermission } from "@stigmer/protos/ai/stigmer/iam/v1/enum_pb";
17
+ /** The permission a wire relation names, or `undefined`. */
18
+ export declare function permissionByEnumName(relation: string): IamPermission | undefined;
19
+ //# sourceMappingURL=permissions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../../src/domain/iampolicy/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EACL,aAAa,EAEd,MAAM,2CAA2C,CAAC;AAInD,4DAA4D;AAC5D,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,GACf,aAAa,GAAG,SAAS,CAS3B"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The permission vocabulary as the wire spells it (20260913.01 slice 5,
3
+ * Q-S5-3): `checkMyPermission` carries its `relation` as a string — the
4
+ * FGA relation name, which is the `IamPermission` member name — while the
5
+ * composed Authorizer's `AuthzCheck` carries the enum. This is the one
6
+ * read from the first spelling to the second. A relation that names no
7
+ * permission is the caller's mistake (INVALID_ARGUMENT in the controller),
8
+ * never a permission nobody holds: the console asks with the ten strings
9
+ * `IamPermission` lists (claim check C4) and a typo should be heard.
10
+ *
11
+ * A Map over the descriptor's values, never the TS enum's reverse index
12
+ * (the `kindsByEnumName` doctrine in pipeline/apiresource-meta.ts): a
13
+ * prototype key or a number spelled as text must resolve to nothing. The
14
+ * zero value `unspecified` is not a permission and is left out.
15
+ */
16
+ import { IamPermission, IamPermissionSchema, } from "@stigmer/protos/ai/stigmer/iam/v1/enum_pb";
17
+ let byName;
18
+ /** The permission a wire relation names, or `undefined`. */
19
+ export function permissionByEnumName(relation) {
20
+ if (byName === undefined) {
21
+ byName = new Map(IamPermissionSchema.values
22
+ .filter((value) => value.number !== IamPermission.unspecified)
23
+ .map((value) => [value.name, value.number]));
24
+ }
25
+ return byName.get(relation);
26
+ }
27
+ //# sourceMappingURL=permissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../../src/domain/iampolicy/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EACL,aAAa,EACb,mBAAmB,GACpB,MAAM,2CAA2C,CAAC;AAEnD,IAAI,MAA8C,CAAC;AAEnD,4DAA4D;AAC5D,MAAM,UAAU,oBAAoB,CAClC,QAAgB;IAEhB,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,GAAG,IAAI,GAAG,CACd,mBAAmB,CAAC,MAAM;aACvB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,aAAa,CAAC,WAAW,CAAC;aAC7D,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAuB,CAAC,CAAC,CAC/D,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Store } from "../../store/interface.js";
2
+ import type { IamPolicyStore } from "./store.js";
3
+ export declare function newResourceIamPolicyStore(store: Store): IamPolicyStore;
4
+ //# sourceMappingURL=resource-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource-store.d.ts","sourceRoot":"","sources":["../../../src/domain/iampolicy/resource-store.ts"],"names":[],"mappings":"AA2CA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAGtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAmBjD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,KAAK,GAAG,cAAc,CAwGtE"}