@stigmer/server 3.37.1 → 3.38.0
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.
- package/dist/boot/compose.d.ts.map +1 -1
- package/dist/boot/compose.js +3 -0
- package/dist/boot/compose.js.map +1 -1
- package/dist/domain/iampolicy/grant-path.d.ts +7 -3
- package/dist/domain/iampolicy/grant-path.d.ts.map +1 -1
- package/dist/domain/iampolicy/grant-path.js +10 -2
- package/dist/domain/iampolicy/grant-path.js.map +1 -1
- package/dist/domain/organization/controller.d.ts +4 -1
- package/dist/domain/organization/controller.d.ts.map +1 -1
- package/dist/domain/organization/controller.js +28 -4
- package/dist/domain/organization/controller.js.map +1 -1
- package/dist/domain/organization/steps.d.ts +22 -0
- package/dist/domain/organization/steps.d.ts.map +1 -1
- package/dist/domain/organization/steps.js +50 -2
- package/dist/domain/organization/steps.js.map +1 -1
- package/dist/extensions/gate-slots.d.ts +14 -1
- package/dist/extensions/gate-slots.d.ts.map +1 -1
- package/dist/extensions/gate-slots.js +1 -0
- package/dist/extensions/gate-slots.js.map +1 -1
- package/dist/pipeline/steps/authorization-tuples.d.ts +6 -2
- package/dist/pipeline/steps/authorization-tuples.d.ts.map +1 -1
- package/dist/pipeline/steps/authorization-tuples.js +6 -2
- package/dist/pipeline/steps/authorization-tuples.js.map +1 -1
- package/package.json +6 -6
- package/src/boot/compose.ts +3 -0
- package/src/domain/iampolicy/__tests__/grant-path.test.ts +40 -7
- package/src/domain/iampolicy/grant-path.ts +19 -5
- package/src/domain/organization/__tests__/organization-delete.test.ts +266 -0
- package/src/domain/organization/controller.ts +40 -8
- package/src/domain/organization/steps.ts +66 -2
- package/src/extensions/__tests__/registry.test.ts +3 -0
- package/src/extensions/gate-slots.ts +14 -0
- package/src/pipeline/steps/authorization-tuples.ts +6 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate-slots.js","sourceRoot":"","sources":["../../src/extensions/gate-slots.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gate-slots.js","sourceRoot":"","sources":["../../src/extensions/gate-slots.ts"],"names":[],"mappings":"AA4FA;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,6CAA6C;IAC7C,8CAA8C;IAC9C,sCAAsC;IACtC,qCAAqC;IACrC,yBAAyB;IACzB,0BAA0B;IAC1B,yCAAyC;IACzC,wCAAwC;IACxC,iCAAiC;IACjC,uBAAuB;CACf,CAAC;AAKX;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAC7D,eAAe,CAChB,CAAC;AAWF;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,SAA4B,EAC5B,IAAkB;IAElB,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACxC,kDAAkD;IAClD,oEAAoE;IACpE,sEAAsE;IACtE,cAAc;IACd,OAAO,KAA0C,CAAC;AACpD,CAAC"}
|
|
@@ -88,8 +88,12 @@ export declare function newCreateAuthorizationTuplesStep<Desc extends DescMessag
|
|
|
88
88
|
/**
|
|
89
89
|
* CleanupIamPolicies — after the store delete in every delete chain.
|
|
90
90
|
* Best-effort by contract: a driver failure is logged and the delete
|
|
91
|
-
* succeeds (Java's DeleteOperationCleanupIamPoliciesStep swallows all
|
|
92
|
-
*
|
|
91
|
+
* succeeds (Java's DeleteOperationCleanupIamPoliciesStep swallows all),
|
|
92
|
+
* because a deleted resource's rows grant nothing once it is gone. The
|
|
93
|
+
* organization is the one kind whose id another caller can take next, so
|
|
94
|
+
* its chain revokes the organization's rows before the row, failing
|
|
95
|
+
* closed (RevokeOrganizationPolicies, domain/organization/steps.ts), and
|
|
96
|
+
* this step is only its backstop there.
|
|
93
97
|
*/
|
|
94
98
|
export declare function newCleanupIamPoliciesStep<Desc extends DescMessage>(lifecycle: ResourceAuthorizationLifecycle | undefined, logger: Logger): PipelineStep<Desc>;
|
|
95
99
|
/** Context key for the pre-update visibility level. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization-tuples.d.ts","sourceRoot":"","sources":["../../../src/pipeline/steps/authorization-tuples.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,wDAAwD,CAAC;AAC/F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qFAAqF,CAAC;AAU3H,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EACV,0BAA0B,EAE1B,8BAA8B,EAC9B,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,4CAA4C,CAAC;AAEpD;;;;;;;;GAQG;AACH,wBAAsB,2BAA2B,CAC/C,SAAS,EAAE,8BAA8B,GAAG,SAAS,EACrD,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,IAAI,CAAC,CAKf;AAGD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAYnD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,qBAAqB,GAC3B,WAAW,CAAC,oBAAoB,CAAC,CAwBnC;AAED,6EAA6E;AAC7E,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,eAAe,EACrB,QAAQ,EAAE,qBAAqB,EAC/B,QAAQ,EAAE,qBAAqB,GAC9B;IACD,QAAQ,CAAC,cAAc,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IAC7D,QAAQ,CAAC,cAAc,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;CAC9D,CAUA;AAgGD;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,eAAe,EACrB,QAAQ,EAAE,OAAO,EACjB,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,MAAM,GACb,oBAAoB,GAAG,SAAS,CAkClC;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,IAAI,SAAS,WAAW,EACvE,SAAS,EAAE,8BAA8B,GAAG,SAAS,EACrD,MAAM,EAAE,MAAM,GACb,YAAY,CAAC,IAAI,CAAC,CAuBpB;AAED
|
|
1
|
+
{"version":3,"file":"authorization-tuples.d.ts","sourceRoot":"","sources":["../../../src/pipeline/steps/authorization-tuples.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,wDAAwD,CAAC;AAC/F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qFAAqF,CAAC;AAU3H,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EACV,0BAA0B,EAE1B,8BAA8B,EAC9B,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,4CAA4C,CAAC;AAEpD;;;;;;;;GAQG;AACH,wBAAsB,2BAA2B,CAC/C,SAAS,EAAE,8BAA8B,GAAG,SAAS,EACrD,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,IAAI,CAAC,CAKf;AAGD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAYnD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,qBAAqB,GAC3B,WAAW,CAAC,oBAAoB,CAAC,CAwBnC;AAED,6EAA6E;AAC7E,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,eAAe,EACrB,QAAQ,EAAE,qBAAqB,EAC/B,QAAQ,EAAE,qBAAqB,GAC9B;IACD,QAAQ,CAAC,cAAc,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IAC7D,QAAQ,CAAC,cAAc,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;CAC9D,CAUA;AAgGD;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,eAAe,EACrB,QAAQ,EAAE,OAAO,EACjB,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,MAAM,GACb,oBAAoB,GAAG,SAAS,CAkClC;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,IAAI,SAAS,WAAW,EACvE,SAAS,EAAE,8BAA8B,GAAG,SAAS,EACrD,MAAM,EAAE,MAAM,GACb,YAAY,CAAC,IAAI,CAAC,CAuBpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,SAAS,WAAW,EAChE,SAAS,EAAE,8BAA8B,GAAG,SAAS,EACrD,MAAM,EAAE,MAAM,GACb,YAAY,CAAC,IAAI,CAAC,CAiCpB;AAED,uDAAuD;AACvD,eAAO,MAAM,kBAAkB,+BAA+B,CAAC;AAE/D;;;;;GAKG;AACH,wBAAgB,mCAAmC,CAAC,IAAI,SAAS,WAAW,EAC1E,WAAW,EAAE,MAAM,GAClB,YAAY,CAAC,IAAI,CAAC,CAYpB;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,SAAS,WAAW,EACpE,SAAS,EAAE,8BAA8B,GAAG,SAAS,EACrD,WAAW,EAAE,MAAM,GAClB,YAAY,CAAC,IAAI,CAAC,CAoCpB"}
|
|
@@ -201,8 +201,12 @@ export function newCreateAuthorizationTuplesStep(lifecycle, logger) {
|
|
|
201
201
|
/**
|
|
202
202
|
* CleanupIamPolicies — after the store delete in every delete chain.
|
|
203
203
|
* Best-effort by contract: a driver failure is logged and the delete
|
|
204
|
-
* succeeds (Java's DeleteOperationCleanupIamPoliciesStep swallows all
|
|
205
|
-
*
|
|
204
|
+
* succeeds (Java's DeleteOperationCleanupIamPoliciesStep swallows all),
|
|
205
|
+
* because a deleted resource's rows grant nothing once it is gone. The
|
|
206
|
+
* organization is the one kind whose id another caller can take next, so
|
|
207
|
+
* its chain revokes the organization's rows before the row, failing
|
|
208
|
+
* closed (RevokeOrganizationPolicies, domain/organization/steps.ts), and
|
|
209
|
+
* this step is only its backstop there.
|
|
206
210
|
*/
|
|
207
211
|
export function newCleanupIamPoliciesStep(lifecycle, logger) {
|
|
208
212
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization-tuples.js","sourceRoot":"","sources":["../../../src/pipeline/steps/authorization-tuples.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"authorization-tuples.js","sourceRoot":"","sources":["../../../src/pipeline/steps/authorization-tuples.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stigmer/server",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.38.0",
|
|
4
4
|
"description": "The Stigmer OSS control plane as a composable library: composeServer, the extension registry and the driver seams a composition builds on. The self-contained deployable of the same server is @stigmer/server-slim.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -63,11 +63,11 @@
|
|
|
63
63
|
"@connectrpc/connect-node": "^2.0.0",
|
|
64
64
|
"@kubernetes/client-node": "2.0.0",
|
|
65
65
|
"@opentelemetry/api": "^1.9.0",
|
|
66
|
-
"@stigmer/outbound": "3.
|
|
67
|
-
"@stigmer/plugin-package": "3.
|
|
68
|
-
"@stigmer/protos": "3.
|
|
69
|
-
"@stigmer/temporal-codecs": "3.
|
|
70
|
-
"@stigmer/zip-structure": "3.
|
|
66
|
+
"@stigmer/outbound": "3.38.0",
|
|
67
|
+
"@stigmer/plugin-package": "3.38.0",
|
|
68
|
+
"@stigmer/protos": "3.38.0",
|
|
69
|
+
"@stigmer/temporal-codecs": "3.38.0",
|
|
70
|
+
"@stigmer/zip-structure": "3.38.0",
|
|
71
71
|
"@temporalio/activity": "1.16.2",
|
|
72
72
|
"@temporalio/client": "1.16.2",
|
|
73
73
|
"@temporalio/common": "1.16.2",
|
package/src/boot/compose.ts
CHANGED
|
@@ -1268,6 +1268,9 @@ export async function composeServer(
|
|
|
1268
1268
|
logger,
|
|
1269
1269
|
authorizer,
|
|
1270
1270
|
gateSteps: extensions.gateSteps,
|
|
1271
|
+
// The delete revokes the organization's rows through the one grant
|
|
1272
|
+
// path, before its row goes (domain/organization/steps.ts).
|
|
1273
|
+
grantPath: iamPolicyGrantPath,
|
|
1271
1274
|
// The role lifecycle and the directory (the identity stage): the
|
|
1272
1275
|
// composed drivers, or open source's under the built-in posture.
|
|
1273
1276
|
authorizationLifecycle: roleLifecycle,
|
|
@@ -14,8 +14,11 @@
|
|
|
14
14
|
* fail-open incident class). The absent arm fires the hook with the
|
|
15
15
|
* spec and no policy, so a composition can still delete a bare tuple
|
|
16
16
|
* written before the row mirror existed.
|
|
17
|
-
* - cleanupResource is bidirectional (as
|
|
18
|
-
* deduplicated, revoking each row
|
|
17
|
+
* - cleanupResource is bidirectional (as principal first, then as
|
|
18
|
+
* target with the owner rows last), deduplicated, revoking each row
|
|
19
|
+
* through the same revoke order; a fault stops it with the owners
|
|
20
|
+
* still holding, since an organization's delete runs it before the
|
|
21
|
+
* organization's row goes and its owner is the one who retries.
|
|
19
22
|
* - revokeOrgAccess revokes the account's direct rows on the
|
|
20
23
|
* organization; the inert org-column arm the cloud carried is gone
|
|
21
24
|
* (Q-OR-9).
|
|
@@ -378,17 +381,19 @@ describe("revoke: onPolicyRevoked before the row delete", () => {
|
|
|
378
381
|
});
|
|
379
382
|
|
|
380
383
|
describe("cleanupResource: bidirectional, deduplicated, each row through the revoke order", () => {
|
|
381
|
-
it("revokes rows where the ref is the
|
|
384
|
+
it("revokes rows where the ref is the principal, then where it is the resource, owners last", async () => {
|
|
382
385
|
const recorded: RecordedEvent[] = [];
|
|
383
386
|
const { policies, path } = pathOver(recorded, recordingLifecycle(recorded));
|
|
384
|
-
const
|
|
387
|
+
const owner = orgRole(ALICE, "owner", "acme");
|
|
388
|
+
const member = orgRole(BOB, "member", "acme");
|
|
385
389
|
const asPrincipal = triple(
|
|
386
390
|
{ kind: "organization", id: "acme" },
|
|
387
391
|
"organization",
|
|
388
392
|
{ kind: "agent", id: AGENT },
|
|
389
393
|
);
|
|
390
394
|
const unrelated = orgRole(ALICE, "member", "globex");
|
|
391
|
-
|
|
395
|
+
// Granted owner first, so the order below is the cleanup's, not the store's.
|
|
396
|
+
for (const spec of [owner, member, asPrincipal, unrelated]) {
|
|
392
397
|
await path.grant(spec, alice);
|
|
393
398
|
}
|
|
394
399
|
recorded.length = 0;
|
|
@@ -399,17 +404,45 @@ describe("cleanupResource: bidirectional, deduplicated, each row through the rev
|
|
|
399
404
|
|
|
400
405
|
expect([...policies.rows.keys()]).toEqual([policyIdFor(unrelated)]);
|
|
401
406
|
expect(recorded).toEqual([
|
|
402
|
-
{ kind: "revoked", id: policyIdFor(asResource), relation: "owner" },
|
|
403
|
-
{ kind: "row-delete", id: policyIdFor(asResource) },
|
|
404
407
|
{
|
|
405
408
|
kind: "revoked",
|
|
406
409
|
id: policyIdFor(asPrincipal),
|
|
407
410
|
relation: "organization",
|
|
408
411
|
},
|
|
409
412
|
{ kind: "row-delete", id: policyIdFor(asPrincipal) },
|
|
413
|
+
{ kind: "revoked", id: policyIdFor(member), relation: "member" },
|
|
414
|
+
{ kind: "row-delete", id: policyIdFor(member) },
|
|
415
|
+
{ kind: "revoked", id: policyIdFor(owner), relation: "owner" },
|
|
416
|
+
{ kind: "row-delete", id: policyIdFor(owner) },
|
|
410
417
|
]);
|
|
411
418
|
});
|
|
412
419
|
|
|
420
|
+
it("stops at the first fault with the owner rows still in place", async () => {
|
|
421
|
+
const recorded: RecordedEvent[] = [];
|
|
422
|
+
const lifecycle = recordingLifecycle(recorded);
|
|
423
|
+
const { policies, path } = pathOver(recorded, {
|
|
424
|
+
...lifecycle,
|
|
425
|
+
onPolicyRevoked: (event) =>
|
|
426
|
+
event.spec.relation === "member"
|
|
427
|
+
? Promise.reject(new Error("tuple delete refused"))
|
|
428
|
+
: lifecycle.onPolicyRevoked!(event),
|
|
429
|
+
});
|
|
430
|
+
const owner = orgRole(ALICE, "owner", "acme");
|
|
431
|
+
const member = orgRole(BOB, "member", "acme");
|
|
432
|
+
for (const spec of [owner, member]) {
|
|
433
|
+
await path.grant(spec, alice);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
await expect(
|
|
437
|
+
path.cleanupResource(
|
|
438
|
+
create(ApiResourceRefSchema, { kind: "organization", id: "acme" }),
|
|
439
|
+
),
|
|
440
|
+
).rejects.toThrow("tuple delete refused");
|
|
441
|
+
|
|
442
|
+
expect(policies.rows.has(policyIdFor(owner))).toBe(true);
|
|
443
|
+
expect(policies.rows.has(policyIdFor(member))).toBe(true);
|
|
444
|
+
});
|
|
445
|
+
|
|
413
446
|
it("a ref that is both principal and resource of one row revokes it once", async () => {
|
|
414
447
|
const recorded: RecordedEvent[] = [];
|
|
415
448
|
const { path } = pathOver(recorded, recordingLifecycle(recorded));
|
|
@@ -59,6 +59,7 @@ import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/
|
|
|
59
59
|
import { ApiResourceMetadataSchema } from "@stigmer/protos/ai/stigmer/commons/apiresource/metadata_pb";
|
|
60
60
|
import type { IamPolicy } from "@stigmer/protos/ai/stigmer/iam/iampolicy/v1/api_pb";
|
|
61
61
|
import { IamPolicySchema } from "@stigmer/protos/ai/stigmer/iam/iampolicy/v1/api_pb";
|
|
62
|
+
import { IamRole } from "@stigmer/protos/ai/stigmer/iam/v1/enum_pb";
|
|
62
63
|
import type {
|
|
63
64
|
ApiResourceRef,
|
|
64
65
|
IamPolicySpec,
|
|
@@ -78,6 +79,9 @@ import { DuplicatePolicyError } from "./store.js";
|
|
|
78
79
|
import type { IamPolicyStore } from "./store.js";
|
|
79
80
|
import { refsOf, requireWellFormedTriple } from "./wire-refusals.js";
|
|
80
81
|
|
|
82
|
+
/** The relation `cleanupResource` revokes last on the ref's own rows. */
|
|
83
|
+
const OWNER_RELATION = IamRole[IamRole.owner];
|
|
84
|
+
|
|
81
85
|
export interface GrantResult {
|
|
82
86
|
readonly policy: IamPolicy;
|
|
83
87
|
/** True when the triple was already held: no row was written, the hook still fired. */
|
|
@@ -99,9 +103,13 @@ export interface IamPolicyGrantPath {
|
|
|
99
103
|
*/
|
|
100
104
|
revokeBySpec(spec: IamPolicySpec): Promise<IamPolicy | undefined>;
|
|
101
105
|
/**
|
|
102
|
-
* Revoke every row naming the ref as its
|
|
103
|
-
* it as its
|
|
104
|
-
* is revoked once. Nothing to clean is a no-op.
|
|
106
|
+
* Revoke every row naming the ref as its principal, then every row naming
|
|
107
|
+
* it as its resource with the `owner` rows last, each through the revoke
|
|
108
|
+
* order; a row that is both is revoked once. Nothing to clean is a no-op.
|
|
109
|
+
* The order matters where the ref still exists: an organization's delete
|
|
110
|
+
* runs this before its row goes and fails on the first fault, so a
|
|
111
|
+
* cleanup that stops partway has not yet removed the owners who may
|
|
112
|
+
* retry it.
|
|
105
113
|
*/
|
|
106
114
|
cleanupResource(ref: ApiResourceRef): Promise<void>;
|
|
107
115
|
/** Revoke every relation the account holds directly on the organization. */
|
|
@@ -209,9 +217,15 @@ export function newIamPolicyGrantPath(
|
|
|
209
217
|
},
|
|
210
218
|
|
|
211
219
|
async cleanupResource(ref): Promise<void> {
|
|
212
|
-
const asResource = await policies.findByResource(ref.kind, ref.id);
|
|
213
220
|
const asPrincipal = await policies.findByPrincipal(ref.kind, ref.id);
|
|
214
|
-
|
|
221
|
+
const asResource = await policies.findByResource(ref.kind, ref.id);
|
|
222
|
+
const isOwner = (policy: IamPolicy): boolean =>
|
|
223
|
+
policy.spec?.relation === OWNER_RELATION;
|
|
224
|
+
for (const policy of distinctById([
|
|
225
|
+
...asPrincipal,
|
|
226
|
+
...asResource.filter((policy) => !isOwner(policy)),
|
|
227
|
+
...asResource.filter(isOwner),
|
|
228
|
+
])) {
|
|
215
229
|
await revokeRow(policy);
|
|
216
230
|
}
|
|
217
231
|
},
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pins the organization delete's order through a composed server in the
|
|
3
|
+
* trusted-local posture: everything that names the organization goes
|
|
4
|
+
* before its row, and a fault stops the delete with the organization in
|
|
5
|
+
* place. An organization's id is its slug and the delete frees the slug for
|
|
6
|
+
* anyone, so a row left behind would belong to the slug's next holder.
|
|
7
|
+
*
|
|
8
|
+
* - the `org-delete:pre-delete` slot runs with the organization loaded
|
|
9
|
+
* and still stored, and its rows still in place;
|
|
10
|
+
* - a slot step's refusal answers its own code and copy, and leaves the
|
|
11
|
+
* organization and its rows;
|
|
12
|
+
* - the organization's policy rows are revoked before its row, as
|
|
13
|
+
* principal and as resource: a revocation fault answers Internal with
|
|
14
|
+
* fixed copy, leaves the organization and its owner row, and a retry
|
|
15
|
+
* completes the delete;
|
|
16
|
+
* - a slug freed by the delete and created again carries none of the old
|
|
17
|
+
* organization's rows.
|
|
18
|
+
*
|
|
19
|
+
* The policy store is the library's in-memory double, composed as the
|
|
20
|
+
* IamPolicy store driver so a test can make one row's delete fault; the
|
|
21
|
+
* grant path, the role lifecycle and the chain are the library's own.
|
|
22
|
+
*/
|
|
23
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
24
|
+
import { tmpdir } from "node:os";
|
|
25
|
+
import path from "node:path";
|
|
26
|
+
|
|
27
|
+
import type { DescMessage } from "@bufbuild/protobuf";
|
|
28
|
+
import { Code, ConnectError, createClient } from "@connectrpc/connect";
|
|
29
|
+
import type { Client, Transport } from "@connectrpc/connect";
|
|
30
|
+
import { createGrpcTransport } from "@connectrpc/connect-node";
|
|
31
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
|
32
|
+
|
|
33
|
+
import { IamPolicyCommandController } from "@stigmer/protos/ai/stigmer/iam/iampolicy/v1/command_pb";
|
|
34
|
+
import type { IamPolicy } from "@stigmer/protos/ai/stigmer/iam/iampolicy/v1/api_pb";
|
|
35
|
+
import type { Organization } from "@stigmer/protos/ai/stigmer/tenancy/organization/v1/api_pb";
|
|
36
|
+
import { OrganizationCommandController } from "@stigmer/protos/ai/stigmer/tenancy/organization/v1/command_pb";
|
|
37
|
+
import { OrganizationQueryController } from "@stigmer/protos/ai/stigmer/tenancy/organization/v1/query_pb";
|
|
38
|
+
|
|
39
|
+
import { loadConfig } from "../../../boot/config.js";
|
|
40
|
+
import { composeServer } from "../../../boot/compose.js";
|
|
41
|
+
import type { ComposedServer } from "../../../boot/compose.js";
|
|
42
|
+
import { createLogger } from "../../../boot/logger.js";
|
|
43
|
+
import type { GateSlotName } from "../../../extensions/gate-slots.js";
|
|
44
|
+
import type { ServerExtension } from "../../../extensions/registry.js";
|
|
45
|
+
import type { PipelineStep } from "../../../pipeline/pipeline.js";
|
|
46
|
+
import { EXISTING_RESOURCE_KEY } from "../../../pipeline/steps/load-existing.js";
|
|
47
|
+
import {
|
|
48
|
+
resetOperatorIdentityForTests,
|
|
49
|
+
setOperatorIdentity,
|
|
50
|
+
} from "../../../pipeline/steps/defaults.js";
|
|
51
|
+
import {
|
|
52
|
+
fakeIamPolicyStore,
|
|
53
|
+
orgRole,
|
|
54
|
+
triple,
|
|
55
|
+
} from "../../iampolicy/__tests__/support.js";
|
|
56
|
+
|
|
57
|
+
const OPERATOR_EMAIL = "operator@example.com";
|
|
58
|
+
const REFUSED_SLUG = "delete-refused";
|
|
59
|
+
const OUTSIDER = "ida_0byc5k14t1e7b7kdxft7hwz1f7";
|
|
60
|
+
const AGENT = "agt_01hzzzzzzzzzzzzzzzzzzzzzzz";
|
|
61
|
+
|
|
62
|
+
async function grpcError(run: () => Promise<unknown>): Promise<ConnectError> {
|
|
63
|
+
try {
|
|
64
|
+
await run();
|
|
65
|
+
} catch (error) {
|
|
66
|
+
if (error instanceof ConnectError) {
|
|
67
|
+
return error;
|
|
68
|
+
}
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
throw new Error("expected the call to fail");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
describe("organization delete (composed server, trusted-local posture)", () => {
|
|
75
|
+
const policies = fakeIamPolicyStore();
|
|
76
|
+
/** A policy id whose delete faults while set: the store answering an error mid-revocation. */
|
|
77
|
+
let faultingDelete: string | undefined;
|
|
78
|
+
const faultablePolicies = {
|
|
79
|
+
...policies,
|
|
80
|
+
async deleteById(id: string): Promise<void> {
|
|
81
|
+
if (id === faultingDelete) {
|
|
82
|
+
throw new Error("policy store unavailable");
|
|
83
|
+
}
|
|
84
|
+
await policies.deleteById(id);
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/** What the slot's step saw, per organization, while it ran. */
|
|
89
|
+
const seenBySlot = new Map<string, { loaded: string; rowsNaming: number }>();
|
|
90
|
+
const slotStep: PipelineStep<DescMessage> = {
|
|
91
|
+
name: "FakeOrgDeleteStep",
|
|
92
|
+
execute: (ctx) => {
|
|
93
|
+
const organization = ctx.get(EXISTING_RESOURCE_KEY) as
|
|
94
|
+
| Organization
|
|
95
|
+
| undefined;
|
|
96
|
+
const id = organization?.metadata?.id ?? "";
|
|
97
|
+
seenBySlot.set(id, { loaded: id, rowsNaming: rowsNaming(id).length });
|
|
98
|
+
if (id === REFUSED_SLUG) {
|
|
99
|
+
throw new ConnectError(
|
|
100
|
+
"fake edition keeps something for this organization",
|
|
101
|
+
Code.FailedPrecondition,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
const unit: ServerExtension = {
|
|
107
|
+
name: "fake-org-delete",
|
|
108
|
+
gateSteps: new Map<GateSlotName, ReadonlyArray<PipelineStep<DescMessage>>>([
|
|
109
|
+
["org-delete:pre-delete", [slotStep]],
|
|
110
|
+
]),
|
|
111
|
+
drivers: { iamPolicyStore: faultablePolicies },
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
let dir: string;
|
|
115
|
+
let server: ComposedServer;
|
|
116
|
+
let transport: Transport;
|
|
117
|
+
let organizations: Client<typeof OrganizationCommandController>;
|
|
118
|
+
let organizationQuery: Client<typeof OrganizationQueryController>;
|
|
119
|
+
/** The platform's own pipeline: the in-process transport's `internal` caller. */
|
|
120
|
+
let platform: Client<typeof IamPolicyCommandController>;
|
|
121
|
+
|
|
122
|
+
function rowsNaming(org: string): IamPolicy[] {
|
|
123
|
+
return [...policies.rows.values()].filter(
|
|
124
|
+
(policy) =>
|
|
125
|
+
(policy.spec?.resource?.kind === "organization" &&
|
|
126
|
+
policy.spec.resource.id === org) ||
|
|
127
|
+
(policy.spec?.principal?.kind === "organization" &&
|
|
128
|
+
policy.spec.principal.id === org),
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** An organization with its creator's owner row, an outsider's member row, and an agent's scope link to it. */
|
|
133
|
+
async function organizationWithRows(slug: string): Promise<void> {
|
|
134
|
+
await organizations.create({
|
|
135
|
+
apiVersion: "tenancy.stigmer.ai/v1",
|
|
136
|
+
kind: "Organization",
|
|
137
|
+
metadata: { name: slug, slug, org: "" },
|
|
138
|
+
spec: { description: "created by the organization delete test" },
|
|
139
|
+
});
|
|
140
|
+
await platform.bootstrapPolicy(orgRole(OUTSIDER, "member", slug));
|
|
141
|
+
await platform.bootstrapPolicy(
|
|
142
|
+
triple({ kind: "organization", id: slug }, "organization", {
|
|
143
|
+
kind: "agent",
|
|
144
|
+
id: AGENT,
|
|
145
|
+
}),
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
beforeAll(async () => {
|
|
150
|
+
dir = mkdtempSync(path.join(tmpdir(), "organization-delete-test-"));
|
|
151
|
+
setOperatorIdentity(OPERATOR_EMAIL, "The Operator");
|
|
152
|
+
server = await composeServer({
|
|
153
|
+
config: loadConfig({
|
|
154
|
+
STIGMER_MODEL_REGISTRY_REFRESH: "off",
|
|
155
|
+
TEMPORAL_HOST_PORT: "127.0.0.1:1",
|
|
156
|
+
DB_PATH: path.join(dir, "stigmer.db"),
|
|
157
|
+
STORAGE_PATH: path.join(dir, "storage"),
|
|
158
|
+
ARTIFACT_LOCAL_BASE_PATH: path.join(dir, "artifacts"),
|
|
159
|
+
STIGMER_OPERATOR_EMAIL: OPERATOR_EMAIL,
|
|
160
|
+
}),
|
|
161
|
+
logger: createLogger({ level: "error", pretty: false, write: () => {} }),
|
|
162
|
+
extensions: [unit],
|
|
163
|
+
portOverride: 0,
|
|
164
|
+
host: "127.0.0.1",
|
|
165
|
+
});
|
|
166
|
+
const port = await server.start();
|
|
167
|
+
transport = createGrpcTransport({ baseUrl: `http://127.0.0.1:${port}` });
|
|
168
|
+
organizations = createClient(OrganizationCommandController, transport);
|
|
169
|
+
organizationQuery = createClient(OrganizationQueryController, transport);
|
|
170
|
+
platform = createClient(
|
|
171
|
+
IamPolicyCommandController,
|
|
172
|
+
server.inProcessTransport,
|
|
173
|
+
);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
afterAll(async () => {
|
|
177
|
+
await server.shutdown();
|
|
178
|
+
resetOperatorIdentityForTests();
|
|
179
|
+
rmSync(dir, { recursive: true, force: true });
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
beforeEach(() => {
|
|
183
|
+
faultingDelete = undefined;
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it("runs the slot with the organization and its rows in place, then removes every row naming it", async () => {
|
|
187
|
+
await organizationWithRows("delete-clean");
|
|
188
|
+
expect(rowsNaming("delete-clean")).toHaveLength(3);
|
|
189
|
+
|
|
190
|
+
await organizations.delete({ value: "delete-clean" });
|
|
191
|
+
|
|
192
|
+
expect(seenBySlot.get("delete-clean")).toEqual({
|
|
193
|
+
loaded: "delete-clean",
|
|
194
|
+
rowsNaming: 3,
|
|
195
|
+
});
|
|
196
|
+
expect(rowsNaming("delete-clean")).toEqual([]);
|
|
197
|
+
const gone = await grpcError(() =>
|
|
198
|
+
organizationQuery.get({ value: "delete-clean" }),
|
|
199
|
+
);
|
|
200
|
+
expect(gone.code).toBe(Code.NotFound);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it("a slot step's refusal answers its own copy and leaves the organization and its rows", async () => {
|
|
204
|
+
await organizationWithRows(REFUSED_SLUG);
|
|
205
|
+
|
|
206
|
+
const refused = await grpcError(() =>
|
|
207
|
+
organizations.delete({ value: REFUSED_SLUG }),
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
expect(refused.code).toBe(Code.FailedPrecondition);
|
|
211
|
+
expect(refused.rawMessage).toBe(
|
|
212
|
+
"fake edition keeps something for this organization",
|
|
213
|
+
);
|
|
214
|
+
expect(
|
|
215
|
+
(await organizationQuery.get({ value: REFUSED_SLUG })).metadata?.id,
|
|
216
|
+
).toBe(REFUSED_SLUG);
|
|
217
|
+
expect(rowsNaming(REFUSED_SLUG)).toHaveLength(3);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it("a revocation fault fails the delete with the organization and its owner in place, and the retry completes it", async () => {
|
|
221
|
+
await organizationWithRows("delete-faults");
|
|
222
|
+
const member = rowsNaming("delete-faults").find(
|
|
223
|
+
(row) => row.spec?.relation === "member",
|
|
224
|
+
);
|
|
225
|
+
faultingDelete = member?.metadata?.id;
|
|
226
|
+
|
|
227
|
+
const failed = await grpcError(() =>
|
|
228
|
+
organizations.delete({ value: "delete-faults" }),
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
expect(failed.code).toBe(Code.Internal);
|
|
232
|
+
expect(failed.rawMessage).toBe(
|
|
233
|
+
"failed to remove the organization's access policies",
|
|
234
|
+
);
|
|
235
|
+
expect(
|
|
236
|
+
(await organizationQuery.get({ value: "delete-faults" })).metadata?.id,
|
|
237
|
+
).toBe("delete-faults");
|
|
238
|
+
// The agent's scope link went first; the revocation stopped at the
|
|
239
|
+
// member row, before the owner row the retry needs.
|
|
240
|
+
expect(
|
|
241
|
+
rowsNaming("delete-faults")
|
|
242
|
+
.map((row) => row.spec?.relation)
|
|
243
|
+
.sort(),
|
|
244
|
+
).toEqual(["member", "owner"]);
|
|
245
|
+
|
|
246
|
+
faultingDelete = undefined;
|
|
247
|
+
await organizations.delete({ value: "delete-faults" });
|
|
248
|
+
expect(rowsNaming("delete-faults")).toEqual([]);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it("a slug freed by the delete and created again carries none of the old organization's rows", async () => {
|
|
252
|
+
await organizationWithRows("delete-reborn");
|
|
253
|
+
await organizations.delete({ value: "delete-reborn" });
|
|
254
|
+
|
|
255
|
+
await organizations.create({
|
|
256
|
+
apiVersion: "tenancy.stigmer.ai/v1",
|
|
257
|
+
kind: "Organization",
|
|
258
|
+
metadata: { name: "delete-reborn", slug: "delete-reborn", org: "" },
|
|
259
|
+
spec: { description: "the slug, taken again" },
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
expect(
|
|
263
|
+
rowsNaming("delete-reborn").map((row) => row.spec?.relation),
|
|
264
|
+
).toEqual(["owner"]);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
@@ -54,6 +54,7 @@ import type { ResolvedGateSteps } from "../../extensions/gate-slots.js";
|
|
|
54
54
|
import { stepsForSlot } from "../../extensions/gate-slots.js";
|
|
55
55
|
import { ALL_ORGANIZATIONS } from "../../extensions/organization-directory.js";
|
|
56
56
|
import type { OrganizationDirectory } from "../../extensions/organization-directory.js";
|
|
57
|
+
import type { IamPolicyGrantPath } from "../iampolicy/grant-path.js";
|
|
57
58
|
import type { ResourceAuthorizationLifecycle } from "../../extensions/resource-authorization.js";
|
|
58
59
|
import { apiResourceKindKey } from "../../pipeline/interceptors/apiresource.js";
|
|
59
60
|
import {
|
|
@@ -105,15 +106,21 @@ import { newValidateVisibilityStep } from "../../pipeline/steps/validate-visibil
|
|
|
105
106
|
import { ResourceNotFoundError } from "../../store/interface.js";
|
|
106
107
|
import type { Store } from "../../store/interface.js";
|
|
107
108
|
import { organizationSearchExtractor } from "./search-extractor.js";
|
|
108
|
-
import {
|
|
109
|
+
import {
|
|
110
|
+
newCheckOrgDuplicateStep,
|
|
111
|
+
newCopySlugToIdStep,
|
|
112
|
+
newRevokeOrganizationPoliciesStep,
|
|
113
|
+
} from "./steps.js";
|
|
109
114
|
|
|
110
115
|
export interface OrganizationControllerDeps {
|
|
111
116
|
readonly store: Store;
|
|
112
117
|
readonly logger: Logger;
|
|
113
118
|
/** The composed authorization seam — the Authorize step at position 1 of every chain calls it (O2, DD-007 §3). */
|
|
114
119
|
readonly authorizer: Authorizer;
|
|
115
|
-
/** The composed slot registrations — this domain's
|
|
120
|
+
/** The composed slot registrations — this domain's create and delete slots (O4). */
|
|
116
121
|
readonly gateSteps: ResolvedGateSteps;
|
|
122
|
+
/** The one grant path: the delete revokes the organization's rows through it before its row goes. */
|
|
123
|
+
readonly grantPath: IamPolicyGrantPath;
|
|
117
124
|
/** The composed tuple-lifecycle driver — undefined = the shared steps no-op (C2). */
|
|
118
125
|
readonly authorizationLifecycle: ResourceAuthorizationLifecycle | undefined;
|
|
119
126
|
/** The composed query directory — undefined = OSS single-tenant behavior (C2). */
|
|
@@ -319,22 +326,38 @@ async function apply(
|
|
|
319
326
|
: update(deps, withResolvedApplyId(OrganizationSchema, org, reqCtx), ctx);
|
|
320
327
|
}
|
|
321
328
|
|
|
322
|
-
/**
|
|
329
|
+
/**
|
|
330
|
+
* Delete — returns the deleted organization (gRPC audit-trail convention).
|
|
331
|
+
*
|
|
332
|
+
* Everything that names the organization goes before its row, and a fault
|
|
333
|
+
* stops the delete with the organization intact: an organization's id is
|
|
334
|
+
* its slug, the delete frees the slug for anyone, and whatever outlived
|
|
335
|
+
* the row would belong to the slug's next holder. So, after the load:
|
|
336
|
+
*
|
|
337
|
+
* 1. the `org-delete:pre-delete` slot, where an edition refuses or
|
|
338
|
+
* removes the rows it keeps for the organization (empty in OSS);
|
|
339
|
+
* 2. RevokeOrganizationPolicies, every policy row naming the
|
|
340
|
+
* organization, through the grant path, never caught;
|
|
341
|
+
* 3. the row;
|
|
342
|
+
* 4. CleanupIamPolicies, the lifecycle's post-delete event: best-effort
|
|
343
|
+
* like every delete chain's, it revokes whatever a concurrent write
|
|
344
|
+
* named the organization with after step 2, and runs a composed
|
|
345
|
+
* driver's post-delete companions;
|
|
346
|
+
* 5. the search entry.
|
|
347
|
+
*/
|
|
323
348
|
async function deleteOrganization(
|
|
324
349
|
deps: OrganizationControllerDeps,
|
|
325
350
|
orgId: OrganizationId,
|
|
326
351
|
ctx: HandlerContext,
|
|
327
352
|
): Promise<Organization> {
|
|
353
|
+
type DeleteInput = typeof OrganizationCommandController.method.delete.input;
|
|
328
354
|
const reqCtx = new RequestContext(
|
|
329
355
|
OrganizationCommandController.method.delete.input,
|
|
330
356
|
orgId,
|
|
331
357
|
callerIdentityOf(ctx),
|
|
332
358
|
kindOf(ctx),
|
|
333
359
|
);
|
|
334
|
-
|
|
335
|
-
"organization-delete",
|
|
336
|
-
deps.logger,
|
|
337
|
-
)
|
|
360
|
+
const builder = newPipeline<DeleteInput>("organization-delete", deps.logger)
|
|
338
361
|
.addStep(
|
|
339
362
|
newAuthorizeStep(
|
|
340
363
|
OrganizationCommandController.method.delete,
|
|
@@ -343,7 +366,16 @@ async function deleteOrganization(
|
|
|
343
366
|
)
|
|
344
367
|
.addStep(newValidateProtoStep())
|
|
345
368
|
.addStep(newExtractResourceIdStep())
|
|
346
|
-
.addStep(newLoadExistingForDeleteStep(deps.store, OrganizationSchema))
|
|
369
|
+
.addStep(newLoadExistingForDeleteStep(deps.store, OrganizationSchema));
|
|
370
|
+
// The pre-delete gate slot (see the doc comment above). Empty in OSS.
|
|
371
|
+
for (const step of stepsForSlot<DeleteInput>(
|
|
372
|
+
deps.gateSteps,
|
|
373
|
+
"org-delete:pre-delete",
|
|
374
|
+
)) {
|
|
375
|
+
builder.addStep(step);
|
|
376
|
+
}
|
|
377
|
+
await builder
|
|
378
|
+
.addStep(newRevokeOrganizationPoliciesStep<DeleteInput>(deps.grantPath))
|
|
347
379
|
.addStep(newDeleteResourceStep(deps.store))
|
|
348
380
|
.addStep(
|
|
349
381
|
newCleanupIamPoliciesStep(deps.authorizationLifecycle, deps.logger),
|