@microagi/alchemy-gcp 0.10.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,9 +12,20 @@ import type * as GCP from "../Providers.ts";
12
12
  * cannot do — **removes it again on delete**, so grants revoke when the
13
13
  * declaring resource leaves the stack.
14
14
  *
15
- * Identity is the `(bucket, role, member)` triple; all three are
16
- * immutable — changing any replaces (the old triple is revoked, the new
17
- * one granted).
15
+ * Identity is the `(bucket, role, member, condition.expression)` tuple;
16
+ * all are immutable — changing any replaces (the old grant is revoked,
17
+ * the new one granted).
18
+ *
19
+ * With a `condition`, the member lands in the binding whose condition
20
+ * **expression** matches (CEL, compared byte-for-byte) — the binding is
21
+ * created with the given title/description if absent. Title and
22
+ * description are create-time metadata only: an existing binding with
23
+ * the same expression but a different title is adopted as-is, never
24
+ * retitled (that lets hand-applied conditional grants converge into the
25
+ * stack without a duplicate binding). Conditional bindings require the
26
+ * bucket to have uniform bucket-level access (GCS rejects conditions
27
+ * otherwise) and policy version 3 — the read-modify-write here always
28
+ * requests/writes version 3.
18
29
  *
19
30
  * The read-modify-write on the shared bucket policy is member-scoped:
20
31
  * exactly one member is added/removed, every foreign role and member is
@@ -36,7 +47,38 @@ import type * as GCP from "../Providers.ts";
36
47
  * "principal://iam.googleapis.com/projects/864268824536/locations/global/workloadIdentityPools/micro-research-cluster-a.svc.id.goog/subject/ns/collab-srl/sa/default",
37
48
  * });
38
49
  * ```
50
+ *
51
+ * @section Prefix-scoped read on a customer bucket
52
+ * @example Conditional grant limited to one object prefix (+ bucket-level list)
53
+ * ```typescript
54
+ * yield* GCP.StorageBucketIamMember("QaDatasetRead", {
55
+ * bucket: "golden-zone-prod-770927",
56
+ * role: "roles/storage.objectViewer",
57
+ * member: "principal://iam.googleapis.com/…/subject/ns/collab-jeffrey-coworking/sa/default",
58
+ * condition: {
59
+ * title: "collab-jeffrey-coworking",
60
+ * expression:
61
+ * 'resource.name.startsWith("projects/_/buckets/golden-zone-prod-770927/objects/qa/") || resource.name == "projects/_/buckets/golden-zone-prod-770927"',
62
+ * },
63
+ * });
64
+ * ```
39
65
  */
66
+ export type StorageBucketIamMemberCondition = {
67
+ /**
68
+ * Binding title — create-time metadata only. NOT identity: a live
69
+ * binding with the same expression but another title is adopted, not
70
+ * retitled/replaced.
71
+ */
72
+ title: string;
73
+ /** Optional human note on the binding. Create-time metadata only. */
74
+ description?: string;
75
+ /**
76
+ * CEL condition expression. Part of the resource identity — compared
77
+ * byte-for-byte against live bindings' expressions, so keep the
78
+ * rendering deterministic. Immutable — replace.
79
+ */
80
+ expression: string;
81
+ };
40
82
  export type StorageBucketIamMemberProps = {
41
83
  /**
42
84
  * Name of the (pre-existing) GCS bucket to grant on. The bucket is
@@ -51,6 +93,14 @@ export type StorageBucketIamMemberProps = {
51
93
  * `group:…`, …). Immutable — replace.
52
94
  */
53
95
  member: string;
96
+ /**
97
+ * Optional IAM Condition scoping the grant (e.g. to an object
98
+ * prefix). Absent → the member joins the role's UNCONDITIONAL
99
+ * binding. The condition **expression** is identity (immutable —
100
+ * replace); title/description are create-time metadata. Requires
101
+ * uniform bucket-level access on the bucket.
102
+ */
103
+ condition?: StorageBucketIamMemberCondition;
54
104
  };
55
105
  export type StorageBucketIamMemberAttributes = {
56
106
  /** Bucket name, threaded through from props. */
@@ -59,6 +109,8 @@ export type StorageBucketIamMemberAttributes = {
59
109
  role: string;
60
110
  /** IAM member, threaded through from props. */
61
111
  member: string;
112
+ /** IAM Condition, threaded through from props (absent = unconditional). */
113
+ condition?: StorageBucketIamMemberCondition;
62
114
  };
63
115
  export type StorageBucketIamMember = Resource<"GCP.StorageBucketIamMember", StorageBucketIamMemberProps, StorageBucketIamMemberAttributes, never, GCP.Providers>;
64
116
  export declare const StorageBucketIamMember: import("alchemy").ResourceClass<StorageBucketIamMember>;
@@ -1 +1 @@
1
- {"version":3,"file":"StorageBucketIamMember.d.ts","sourceRoot":"","sources":["../../src/Storage/StorageBucketIamMember.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAI7C,OAAO,KAAK,KAAK,GAAG,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG;IAC7C,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAC3C,4BAA4B,EAC5B,2BAA2B,EAC3B,gCAAgC,EAChC,KAAK,EACL,GAAG,CAAC,SAAS,CACd,CAAC;AAEF,eAAO,MAAM,sBAAsB,yDAElC,CAAC;AAEF,eAAO,MAAM,8BAA8B,yLAgKxC,CAAC"}
1
+ {"version":3,"file":"StorageBucketIamMember.d.ts","sourceRoot":"","sources":["../../src/Storage/StorageBucketIamMember.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAI7C,OAAO,KAAK,KAAK,GAAG,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,MAAM,MAAM,+BAA+B,GAAG;IAC5C;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,+BAA+B,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG;IAC7C,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,SAAS,CAAC,EAAE,+BAA+B,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAC3C,4BAA4B,EAC5B,2BAA2B,EAC3B,gCAAgC,EAChC,KAAK,EACL,GAAG,CAAC,SAAS,CACd,CAAC;AAEF,eAAO,MAAM,sBAAsB,yDAElC,CAAC;AAEF,eAAO,MAAM,8BAA8B,yLAyOxC,CAAC"}
@@ -19,12 +19,20 @@ export const StorageBucketIamMemberProvider = () => Provider.effect(StorageBucke
19
19
  while: (e) => e?._tag !== "ConfigError",
20
20
  schedule: Schedule.exponential(Duration.seconds(2)).pipe(Schedule.both(Schedule.recurs(8))),
21
21
  }));
22
- // Membership check scoped to the unconditional binding for `role`
23
- // conditional bindings are someone else's and never touched.
24
- const hasMember = (policy, role, member) => (policy.bindings ?? []).some((b) => b.role === role && !b.condition && (b.members ?? []).includes(member));
22
+ // Binding selector: with no condition, ONLY the unconditional
23
+ // binding for `role` (conditional bindings are someone else's);
24
+ // with a condition, the binding whose expression matches
25
+ // byte-for-byte — title/description deliberately ignored so
26
+ // hand-applied grants with the same expression are adopted.
27
+ const bindingMatches = (b, role, condition) => b.role === role &&
28
+ (condition
29
+ ? b.condition?.expression === condition.expression
30
+ : !b.condition);
31
+ const hasMember = (policy, role, member, condition) => (policy.bindings ?? []).some((b) => bindingMatches(b, role, condition) &&
32
+ (b.members ?? []).includes(member));
25
33
  return {
26
- // Identity IS the triple; all three are static strings.
27
- stables: ["bucket", "role", "member"],
34
+ // Identity IS the tuple; all fields are static values.
35
+ stables: ["bucket", "role", "member", "condition"],
28
36
  diff: Effect.fn(function* ({ news, olds = {}, output }) {
29
37
  if (!isResolved(news))
30
38
  return undefined;
@@ -44,6 +52,19 @@ export const StorageBucketIamMemberProvider = () => Provider.effect(StorageBucke
44
52
  (priorMember && priorMember !== news.member)) {
45
53
  return { action: "replace" };
46
54
  }
55
+ // Condition expression is identity too — but only when a prior
56
+ // identity exists at all (a partially-persisted record with no
57
+ // bucket names no grant to revoke). Absent condition compares
58
+ // as "" so unconditional↔conditional flips replace, while a
59
+ // 0.10.x record (no condition attribute) vs. unconditional
60
+ // props stays a no-op. `||` like the triple above: an empty
61
+ // persisted expression is NOT a prior identity and must not
62
+ // block the olds fallback.
63
+ const priorCond = output?.condition?.expression || olds.condition?.expression || "";
64
+ const newsCond = news.condition?.expression ?? "";
65
+ if (priorBucket && priorCond !== newsCond) {
66
+ return { action: "replace" };
67
+ }
47
68
  return undefined;
48
69
  }),
49
70
  reconcile: Effect.fn(function* ({ news }) {
@@ -54,31 +75,64 @@ export const StorageBucketIamMemberProvider = () => Provider.effect(StorageBucke
54
75
  }).pipe(Effect.catchTag("NotFound", () => Effect.fail(new ConfigError({
55
76
  message: `Bucket ${news.bucket} does not exist — StorageBucketIamMember grants on pre-existing buckets only.`,
56
77
  }))));
57
- if (hasMember(current, news.role, news.member))
78
+ if (hasMember(current, news.role, news.member, news.condition)) {
58
79
  return;
80
+ }
59
81
  const bindings = (current.bindings ?? []).map((b) => ({
60
82
  ...b,
61
83
  members: [...(b.members ?? [])],
62
84
  }));
63
- const existing = bindings.find((b) => b.role === news.role && !b.condition);
85
+ const existing = bindings.find((b) => bindingMatches(b, news.role, news.condition));
64
86
  if (existing) {
65
87
  existing.members = [...(existing.members ?? []), news.member];
66
88
  }
67
89
  else {
68
- bindings.push({ role: news.role, members: [news.member] });
90
+ bindings.push({
91
+ role: news.role,
92
+ members: [news.member],
93
+ ...(news.condition
94
+ ? {
95
+ condition: {
96
+ title: news.condition.title,
97
+ ...(news.condition.description
98
+ ? { description: news.condition.description }
99
+ : {}),
100
+ expression: news.condition.expression,
101
+ },
102
+ }
103
+ : {}),
104
+ });
69
105
  }
70
106
  yield* setIamPolicyBuckets({
71
107
  bucket: news.bucket,
72
108
  body: { ...current, bindings, version: 3 },
73
109
  });
74
110
  }));
75
- return { bucket: news.bucket, role: news.role, member: news.member };
111
+ return {
112
+ bucket: news.bucket,
113
+ role: news.role,
114
+ member: news.member,
115
+ ...(news.condition ? { condition: news.condition } : {}),
116
+ };
76
117
  }),
77
- delete: Effect.fn(function* ({ output }) {
118
+ delete: Effect.fn(function* ({ output, olds }) {
78
119
  // Partially-persisted attributes (empty fields) name no real
79
120
  // grant — nothing to revoke, and getIamPolicy("") would 4xx.
80
121
  if (!output.bucket || !output.role || !output.member)
81
122
  return;
123
+ // Prior condition with an olds fallback: if the persisted
124
+ // attributes lost the condition while the live binding is
125
+ // conditional, matching without it would target the
126
+ // UNCONDITIONAL binding — either revoking a member some other
127
+ // resource owns there, or no-op'ing and leaving the scoped
128
+ // grant behind. Selected on expression TRUTHINESS (same rule
129
+ // as diff's `||` chain): a stub condition with an empty
130
+ // expression is not a prior identity and must not block olds.
131
+ const condition = output.condition?.expression
132
+ ? output.condition
133
+ : olds?.condition?.expression
134
+ ? olds.condition
135
+ : undefined;
82
136
  yield* etagRetry(Effect.gen(function* () {
83
137
  const current = yield* getIamPolicyBuckets({
84
138
  bucket: output.bucket,
@@ -87,14 +141,15 @@ export const StorageBucketIamMemberProvider = () => Provider.effect(StorageBucke
87
141
  // Bucket gone (or unreadable because gone) — the grant
88
142
  // went with it; idempotent success.
89
143
  Effect.catchTag("NotFound", () => Effect.succeed(undefined)));
90
- if (!current || !hasMember(current, output.role, output.member)) {
144
+ if (!current ||
145
+ !hasMember(current, output.role, output.member, condition)) {
91
146
  return;
92
147
  }
93
- // Remove exactly our member from the unconditional binding;
148
+ // Remove exactly our member from the matched binding;
94
149
  // drop the binding entirely if that empties it (GCS rejects
95
150
  // bindings with zero members).
96
151
  const bindings = (current.bindings ?? [])
97
- .map((b) => b.role === output.role && !b.condition
152
+ .map((b) => bindingMatches(b, output.role, condition)
98
153
  ? {
99
154
  ...b,
100
155
  members: (b.members ?? []).filter((m) => m !== output.member),
@@ -111,6 +166,7 @@ export const StorageBucketIamMemberProvider = () => Provider.effect(StorageBucke
111
166
  const bucket = output?.bucket ?? olds?.bucket;
112
167
  const role = output?.role ?? olds?.role;
113
168
  const member = output?.member ?? olds?.member;
169
+ const condition = output?.condition ?? olds?.condition;
114
170
  if (!bucket || !role || !member)
115
171
  return undefined;
116
172
  const current = yield* getIamPolicyBuckets({
@@ -121,9 +177,14 @@ export const StorageBucketIamMemberProvider = () => Provider.effect(StorageBucke
121
177
  return undefined;
122
178
  // Absent member → undefined: the engine treats that as drift
123
179
  // and the next plan re-grants.
124
- if (!hasMember(current, role, member))
180
+ if (!hasMember(current, role, member, condition))
125
181
  return undefined;
126
- return { bucket, role, member };
182
+ return {
183
+ bucket,
184
+ role,
185
+ member,
186
+ ...(condition ? { condition } : {}),
187
+ };
127
188
  }),
128
189
  };
129
190
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"StorageBucketIamMember.js","sourceRoot":"","sources":["../../src/Storage/StorageBucketIamMember.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"StorageBucketIamMember.js","sourceRoot":"","sources":["../../src/Storage/StorageBucketIamMember.ts"],"names":[],"mappings":"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"}
@@ -2,5 +2,5 @@ export { StorageBucket, StorageBucketProvider, } from "./Bucket.ts";
2
2
  export type { StorageBucketProps, StorageBucketIamBinding, StorageBucketBindingContract, } from "./Bucket.ts";
3
3
  export * from "./BucketIamMember.ts";
4
4
  export { StorageBucketIamMember, StorageBucketIamMemberProvider, } from "./StorageBucketIamMember.ts";
5
- export type { StorageBucketIamMemberProps, StorageBucketIamMemberAttributes, } from "./StorageBucketIamMember.ts";
5
+ export type { StorageBucketIamMemberProps, StorageBucketIamMemberAttributes, StorageBucketIamMemberCondition, } from "./StorageBucketIamMember.ts";
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,kBAAkB,EAClB,uBAAuB,EACvB,4BAA4B,GAC7B,MAAM,aAAa,CAAC;AACrB,cAAc,sBAAsB,CAAC;AACrC,OAAO,EACL,sBAAsB,EACtB,8BAA8B,GAC/B,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,2BAA2B,EAC3B,gCAAgC,GACjC,MAAM,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,kBAAkB,EAClB,uBAAuB,EACvB,4BAA4B,GAC7B,MAAM,aAAa,CAAC;AACrB,cAAc,sBAAsB,CAAC;AACrC,OAAO,EACL,sBAAsB,EACtB,8BAA8B,GAC/B,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,2BAA2B,EAC3B,gCAAgC,EAChC,+BAA+B,GAChC,MAAM,6BAA6B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microagi/alchemy-gcp",
3
- "version": "0.10.0",
3
+ "version": "0.11.1",
4
4
  "description": "GCP provider for Alchemy v2 (Effect-based IaC). Resources for Project, ServiceAccount, Cluster, NodePool, Compute, ManagedLustre, ServiceUsage, ServiceNetworking, Cloud Run (Service + Job + IAM), Cloud SQL (Instance + Database + User with IAM database authn), Artifact Registry (Docker repositories, standard + remote pull-through caches), Kubernetes (typed Secret + generic SSA Manifest + Helm release), with ADC-backed credentials and target-side IAM bindings.",
5
5
  "keywords": [
6
6
  "alchemy",
@@ -19,9 +19,20 @@ import type * as GCP from "../Providers.ts";
19
19
  * cannot do — **removes it again on delete**, so grants revoke when the
20
20
  * declaring resource leaves the stack.
21
21
  *
22
- * Identity is the `(bucket, role, member)` triple; all three are
23
- * immutable — changing any replaces (the old triple is revoked, the new
24
- * one granted).
22
+ * Identity is the `(bucket, role, member, condition.expression)` tuple;
23
+ * all are immutable — changing any replaces (the old grant is revoked,
24
+ * the new one granted).
25
+ *
26
+ * With a `condition`, the member lands in the binding whose condition
27
+ * **expression** matches (CEL, compared byte-for-byte) — the binding is
28
+ * created with the given title/description if absent. Title and
29
+ * description are create-time metadata only: an existing binding with
30
+ * the same expression but a different title is adopted as-is, never
31
+ * retitled (that lets hand-applied conditional grants converge into the
32
+ * stack without a duplicate binding). Conditional bindings require the
33
+ * bucket to have uniform bucket-level access (GCS rejects conditions
34
+ * otherwise) and policy version 3 — the read-modify-write here always
35
+ * requests/writes version 3.
25
36
  *
26
37
  * The read-modify-write on the shared bucket policy is member-scoped:
27
38
  * exactly one member is added/removed, every foreign role and member is
@@ -43,7 +54,39 @@ import type * as GCP from "../Providers.ts";
43
54
  * "principal://iam.googleapis.com/projects/864268824536/locations/global/workloadIdentityPools/micro-research-cluster-a.svc.id.goog/subject/ns/collab-srl/sa/default",
44
55
  * });
45
56
  * ```
57
+ *
58
+ * @section Prefix-scoped read on a customer bucket
59
+ * @example Conditional grant limited to one object prefix (+ bucket-level list)
60
+ * ```typescript
61
+ * yield* GCP.StorageBucketIamMember("QaDatasetRead", {
62
+ * bucket: "golden-zone-prod-770927",
63
+ * role: "roles/storage.objectViewer",
64
+ * member: "principal://iam.googleapis.com/…/subject/ns/collab-jeffrey-coworking/sa/default",
65
+ * condition: {
66
+ * title: "collab-jeffrey-coworking",
67
+ * expression:
68
+ * 'resource.name.startsWith("projects/_/buckets/golden-zone-prod-770927/objects/qa/") || resource.name == "projects/_/buckets/golden-zone-prod-770927"',
69
+ * },
70
+ * });
71
+ * ```
46
72
  */
73
+ export type StorageBucketIamMemberCondition = {
74
+ /**
75
+ * Binding title — create-time metadata only. NOT identity: a live
76
+ * binding with the same expression but another title is adopted, not
77
+ * retitled/replaced.
78
+ */
79
+ title: string;
80
+ /** Optional human note on the binding. Create-time metadata only. */
81
+ description?: string;
82
+ /**
83
+ * CEL condition expression. Part of the resource identity — compared
84
+ * byte-for-byte against live bindings' expressions, so keep the
85
+ * rendering deterministic. Immutable — replace.
86
+ */
87
+ expression: string;
88
+ };
89
+
47
90
  export type StorageBucketIamMemberProps = {
48
91
  /**
49
92
  * Name of the (pre-existing) GCS bucket to grant on. The bucket is
@@ -58,6 +101,14 @@ export type StorageBucketIamMemberProps = {
58
101
  * `group:…`, …). Immutable — replace.
59
102
  */
60
103
  member: string;
104
+ /**
105
+ * Optional IAM Condition scoping the grant (e.g. to an object
106
+ * prefix). Absent → the member joins the role's UNCONDITIONAL
107
+ * binding. The condition **expression** is identity (immutable —
108
+ * replace); title/description are create-time metadata. Requires
109
+ * uniform bucket-level access on the bucket.
110
+ */
111
+ condition?: StorageBucketIamMemberCondition;
61
112
  };
62
113
 
63
114
  export type StorageBucketIamMemberAttributes = {
@@ -67,6 +118,8 @@ export type StorageBucketIamMemberAttributes = {
67
118
  role: string;
68
119
  /** IAM member, threaded through from props. */
69
120
  member: string;
121
+ /** IAM Condition, threaded through from props (absent = unconditional). */
122
+ condition?: StorageBucketIamMemberCondition;
70
123
  };
71
124
 
72
125
  export type StorageBucketIamMember = Resource<
@@ -103,20 +156,36 @@ export const StorageBucketIamMemberProvider = () =>
103
156
  }),
104
157
  );
105
158
 
106
- // Membership check scoped to the unconditional binding for `role`
107
- // conditional bindings are someone else's and never touched.
159
+ // Binding selector: with no condition, ONLY the unconditional
160
+ // binding for `role` (conditional bindings are someone else's);
161
+ // with a condition, the binding whose expression matches
162
+ // byte-for-byte — title/description deliberately ignored so
163
+ // hand-applied grants with the same expression are adopted.
164
+ const bindingMatches = (
165
+ b: { role?: string; condition?: { expression?: string } },
166
+ role: string,
167
+ condition?: StorageBucketIamMemberCondition,
168
+ ) =>
169
+ b.role === role &&
170
+ (condition
171
+ ? b.condition?.expression === condition.expression
172
+ : !b.condition);
173
+
108
174
  const hasMember = (
109
175
  policy: storage.Policy,
110
176
  role: string,
111
177
  member: string,
178
+ condition?: StorageBucketIamMemberCondition,
112
179
  ) =>
113
180
  (policy.bindings ?? []).some(
114
- (b) => b.role === role && !b.condition && (b.members ?? []).includes(member),
181
+ (b) =>
182
+ bindingMatches(b, role, condition) &&
183
+ (b.members ?? []).includes(member),
115
184
  );
116
185
 
117
186
  return {
118
- // Identity IS the triple; all three are static strings.
119
- stables: ["bucket", "role", "member"],
187
+ // Identity IS the tuple; all fields are static values.
188
+ stables: ["bucket", "role", "member", "condition"],
120
189
  diff: Effect.fn(function* ({ news, olds = {}, output }) {
121
190
  if (!isResolved(news)) return undefined;
122
191
  // Prior identity from persisted attributes first, then olds —
@@ -137,6 +206,20 @@ export const StorageBucketIamMemberProvider = () =>
137
206
  ) {
138
207
  return { action: "replace" } as const;
139
208
  }
209
+ // Condition expression is identity too — but only when a prior
210
+ // identity exists at all (a partially-persisted record with no
211
+ // bucket names no grant to revoke). Absent condition compares
212
+ // as "" so unconditional↔conditional flips replace, while a
213
+ // 0.10.x record (no condition attribute) vs. unconditional
214
+ // props stays a no-op. `||` like the triple above: an empty
215
+ // persisted expression is NOT a prior identity and must not
216
+ // block the olds fallback.
217
+ const priorCond =
218
+ output?.condition?.expression || olds.condition?.expression || "";
219
+ const newsCond = news.condition?.expression ?? "";
220
+ if (priorBucket && priorCond !== newsCond) {
221
+ return { action: "replace" } as const;
222
+ }
140
223
  return undefined;
141
224
  }),
142
225
  reconcile: Effect.fn(function* ({ news }) {
@@ -154,19 +237,35 @@ export const StorageBucketIamMemberProvider = () =>
154
237
  ),
155
238
  ),
156
239
  );
157
- if (hasMember(current, news.role, news.member)) return;
240
+ if (hasMember(current, news.role, news.member, news.condition)) {
241
+ return;
242
+ }
158
243
 
159
244
  const bindings = (current.bindings ?? []).map((b) => ({
160
245
  ...b,
161
246
  members: [...(b.members ?? [])],
162
247
  }));
163
- const existing = bindings.find(
164
- (b) => b.role === news.role && !b.condition,
248
+ const existing = bindings.find((b) =>
249
+ bindingMatches(b, news.role, news.condition),
165
250
  );
166
251
  if (existing) {
167
252
  existing.members = [...(existing.members ?? []), news.member];
168
253
  } else {
169
- bindings.push({ role: news.role, members: [news.member] });
254
+ bindings.push({
255
+ role: news.role,
256
+ members: [news.member],
257
+ ...(news.condition
258
+ ? {
259
+ condition: {
260
+ title: news.condition.title,
261
+ ...(news.condition.description
262
+ ? { description: news.condition.description }
263
+ : {}),
264
+ expression: news.condition.expression,
265
+ },
266
+ }
267
+ : {}),
268
+ });
170
269
  }
171
270
  yield* setIamPolicyBuckets({
172
271
  bucket: news.bucket,
@@ -174,12 +273,30 @@ export const StorageBucketIamMemberProvider = () =>
174
273
  });
175
274
  }),
176
275
  );
177
- return { bucket: news.bucket, role: news.role, member: news.member };
276
+ return {
277
+ bucket: news.bucket,
278
+ role: news.role,
279
+ member: news.member,
280
+ ...(news.condition ? { condition: news.condition } : {}),
281
+ };
178
282
  }),
179
- delete: Effect.fn(function* ({ output }) {
283
+ delete: Effect.fn(function* ({ output, olds }) {
180
284
  // Partially-persisted attributes (empty fields) name no real
181
285
  // grant — nothing to revoke, and getIamPolicy("") would 4xx.
182
286
  if (!output.bucket || !output.role || !output.member) return;
287
+ // Prior condition with an olds fallback: if the persisted
288
+ // attributes lost the condition while the live binding is
289
+ // conditional, matching without it would target the
290
+ // UNCONDITIONAL binding — either revoking a member some other
291
+ // resource owns there, or no-op'ing and leaving the scoped
292
+ // grant behind. Selected on expression TRUTHINESS (same rule
293
+ // as diff's `||` chain): a stub condition with an empty
294
+ // expression is not a prior identity and must not block olds.
295
+ const condition = output.condition?.expression
296
+ ? output.condition
297
+ : olds?.condition?.expression
298
+ ? olds.condition
299
+ : undefined;
183
300
  yield* etagRetry(
184
301
  Effect.gen(function* () {
185
302
  const current = yield* getIamPolicyBuckets({
@@ -192,15 +309,18 @@ export const StorageBucketIamMemberProvider = () =>
192
309
  Effect.succeed(undefined as storage.Policy | undefined),
193
310
  ),
194
311
  );
195
- if (!current || !hasMember(current, output.role, output.member)) {
312
+ if (
313
+ !current ||
314
+ !hasMember(current, output.role, output.member, condition)
315
+ ) {
196
316
  return;
197
317
  }
198
- // Remove exactly our member from the unconditional binding;
318
+ // Remove exactly our member from the matched binding;
199
319
  // drop the binding entirely if that empties it (GCS rejects
200
320
  // bindings with zero members).
201
321
  const bindings = (current.bindings ?? [])
202
322
  .map((b) =>
203
- b.role === output.role && !b.condition
323
+ bindingMatches(b, output.role, condition)
204
324
  ? {
205
325
  ...b,
206
326
  members: (b.members ?? []).filter(
@@ -221,6 +341,7 @@ export const StorageBucketIamMemberProvider = () =>
221
341
  const bucket = output?.bucket ?? olds?.bucket;
222
342
  const role = output?.role ?? olds?.role;
223
343
  const member = output?.member ?? olds?.member;
344
+ const condition = output?.condition ?? olds?.condition;
224
345
  if (!bucket || !role || !member) return undefined;
225
346
  const current = yield* getIamPolicyBuckets({
226
347
  bucket,
@@ -236,8 +357,13 @@ export const StorageBucketIamMemberProvider = () =>
236
357
  if (!current) return undefined;
237
358
  // Absent member → undefined: the engine treats that as drift
238
359
  // and the next plan re-grants.
239
- if (!hasMember(current, role, member)) return undefined;
240
- return { bucket, role, member };
360
+ if (!hasMember(current, role, member, condition)) return undefined;
361
+ return {
362
+ bucket,
363
+ role,
364
+ member,
365
+ ...(condition ? { condition } : {}),
366
+ };
241
367
  }),
242
368
  };
243
369
  }),
@@ -15,4 +15,5 @@ export {
15
15
  export type {
16
16
  StorageBucketIamMemberProps,
17
17
  StorageBucketIamMemberAttributes,
18
+ StorageBucketIamMemberCondition,
18
19
  } from "./StorageBucketIamMember.ts";