@cosmicdrift/kumiko-bundled-features 0.218.0 → 0.219.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-bundled-features",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.219.0",
|
|
4
4
|
"description": "Built-in features — tenant, user, auth, delivery. The stuff you'd rewrite anyway, already typed.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -126,12 +126,12 @@
|
|
|
126
126
|
"./step-dispatcher": "./src/step-dispatcher/index.ts"
|
|
127
127
|
},
|
|
128
128
|
"dependencies": {
|
|
129
|
-
"@cosmicdrift/kumiko-dispatcher-live": "0.
|
|
130
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
131
|
-
"@cosmicdrift/kumiko-headless": "0.
|
|
132
|
-
"@cosmicdrift/kumiko-renderer": "0.
|
|
133
|
-
"@cosmicdrift/kumiko-renderer-web": "0.
|
|
134
|
-
"@cosmicdrift/kumiko-types": "0.
|
|
129
|
+
"@cosmicdrift/kumiko-dispatcher-live": "0.219.0",
|
|
130
|
+
"@cosmicdrift/kumiko-framework": "0.219.0",
|
|
131
|
+
"@cosmicdrift/kumiko-headless": "0.219.0",
|
|
132
|
+
"@cosmicdrift/kumiko-renderer": "0.219.0",
|
|
133
|
+
"@cosmicdrift/kumiko-renderer-web": "0.219.0",
|
|
134
|
+
"@cosmicdrift/kumiko-types": "0.219.0",
|
|
135
135
|
"@mollie/api-client": "^4.5.0",
|
|
136
136
|
"@node-rs/argon2": "^2.0.2",
|
|
137
137
|
"@types/mailparser": "^3.4.6",
|
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
"devDependencies": {
|
|
161
161
|
"@testing-library/user-event": "^14.6.1",
|
|
162
162
|
"@types/qrcode": "^1.5.5",
|
|
163
|
-
"@cosmicdrift/kumiko-locale-de": "0.
|
|
164
|
-
"@cosmicdrift/kumiko-locale-es": "0.
|
|
163
|
+
"@cosmicdrift/kumiko-locale-de": "0.219.0",
|
|
164
|
+
"@cosmicdrift/kumiko-locale-es": "0.219.0"
|
|
165
165
|
}
|
|
166
166
|
}
|
|
@@ -321,6 +321,19 @@ describe("privilege escalation via invite role", () => {
|
|
|
321
321
|
expectErrorIncludes(err, "unassignable_membership_role");
|
|
322
322
|
});
|
|
323
323
|
|
|
324
|
+
test("TenantAdmin can invite as TenantAdmin (same-rank owner invite)", async () => {
|
|
325
|
+
await stack.http.write(
|
|
326
|
+
AuthHandlers.inviteCreate,
|
|
327
|
+
{ email: "co-owner@example.com", role: "TenantAdmin" },
|
|
328
|
+
tenantAdminA(),
|
|
329
|
+
);
|
|
330
|
+
const rows = await selectMany(stack.db, tenantInvitationsTable, {
|
|
331
|
+
email: "co-owner@example.com",
|
|
332
|
+
});
|
|
333
|
+
expect(rows).toHaveLength(1);
|
|
334
|
+
expect(rows[0]?.["role"]).toBe("TenantAdmin");
|
|
335
|
+
});
|
|
336
|
+
|
|
324
337
|
test("TenantAdmin cannot invite with unknown unranked role (elevation guard)", async () => {
|
|
325
338
|
const err = await stack.http.writeErr(
|
|
326
339
|
AuthHandlers.inviteCreate,
|
package/src/tenant/changes.json
CHANGED
|
@@ -1,33 +1,39 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.219.0",
|
|
4
|
+
"type": "improvement",
|
|
5
|
+
"title": "Invite/member-roles pickers include TenantAdmin",
|
|
6
|
+
"detail": "DEFAULT_INVITE_ROLE_OPTIONS adds TenantAdmin so SystemAdmin/TenantAdmin can invite owners. SystemAdmin stays global-only (user.roles), never a membership invite option."
|
|
7
|
+
},
|
|
2
8
|
{
|
|
3
9
|
"version": "0.209.0",
|
|
4
10
|
"type": "improvement",
|
|
5
11
|
"title": "tenant: single /members screen replaces the members-card/pending-card split (#2223)",
|
|
6
|
-
"detail": "New `tenant:query:team:list` handler merges active memberships and pending invitations into one projectionList screen (`membersScreen`), with a `status` facet, sortable/searchable columns, and a danger-styled `cancel-invitation` row action visible only on pending rows. `createTenantFeature({ inviteScreen: true })` additionally wires a drawer-hosted invite actionForm onto the toolbar (bound to auth-email-password's `invite-create` handler)
|
|
12
|
+
"detail": "New `tenant:query:team:list` handler merges active memberships and pending invitations into one projectionList screen (`membersScreen`), with a `status` facet, sortable/searchable columns, and a danger-styled `cancel-invitation` row action visible only on pending rows. `createTenantFeature({ inviteScreen: true })` additionally wires a drawer-hosted invite actionForm onto the toolbar (bound to auth-email-password's `invite-create` handler) \u2014 off by default, and only safe to enable once the app also configures `createAuthEmailPasswordFeature({ invite: {...} })`, since the boot validator rejects the actionForm's cross-feature handler QN otherwise. The old `members`/`invitations` query handlers and their custom `MembersScreen` component are unaffected and stay registered for existing callers; `updateMemberRoles` stays SystemAdmin-only and off this screen."
|
|
7
13
|
},
|
|
8
14
|
{
|
|
9
15
|
"version": "0.165.0",
|
|
10
16
|
"type": "fix",
|
|
11
17
|
"title": "resolveRawDb: removed redundant null check",
|
|
12
|
-
"detail": "CodeQL flagged db !== null after if (!db)
|
|
18
|
+
"detail": "CodeQL flagged db !== null after if (!db) \u2014 truthiness already excludes null. Internal cleanup, no API break."
|
|
13
19
|
},
|
|
14
20
|
{
|
|
15
21
|
"version": "0.165.0",
|
|
16
22
|
"type": "fix",
|
|
17
23
|
"title": "Seed hook: explicit SessionUser typing",
|
|
18
|
-
"detail": "Fixed tenant seeding type annotation
|
|
24
|
+
"detail": "Fixed tenant seeding type annotation \u2014 prevents implicit any propagation in seed handlers."
|
|
19
25
|
},
|
|
20
26
|
{
|
|
21
27
|
"version": "0.165.0",
|
|
22
28
|
"type": "fix",
|
|
23
29
|
"title": "Seed afterCommit + real tenant rescope",
|
|
24
|
-
"detail": "ScheduleAfterCommit now available on HandlerContext
|
|
25
|
-
"migration": "Only affects custom seed handlers using fireEntityPostSave
|
|
30
|
+
"detail": "ScheduleAfterCommit now available on HandlerContext \u2014 fireEntityPostSave queues after TX commit instead of mid-transaction. DB/notify/hasFeature/_tenantId are correctly rescoped when targeting an entity's tenant.",
|
|
31
|
+
"migration": "Only affects custom seed handlers using fireEntityPostSave \u2014 now afterCommit-compatible."
|
|
26
32
|
},
|
|
27
33
|
{
|
|
28
34
|
"version": "0.163.0",
|
|
29
35
|
"type": "improvement",
|
|
30
36
|
"title": "tenant: seedTenant fires entity postSave hooks (#1463).",
|
|
31
|
-
"detail": "tenant: seedTenant fires entity postSave hooks (#1463). `seedTenant` writes through the raw event-store executor, which never fired postSave hooks
|
|
37
|
+
"detail": "tenant: seedTenant fires entity postSave hooks (#1463). `seedTenant` writes through the raw event-store executor, which never fired postSave hooks \u2014 self-signup (`provisionSignupAccount` \u2192 `signup-confirm`) silently skipped feature-registered entity hooks like tier-engine's auto-default-tier and app-level auto-default-compliance, leaving new tenants without a tier/compliance row. `seedTenant` and `provisionSignupAccount` take a new optional `hooks: { registry, context }` param; passing it fires the same entity-scoped postSave hooks the dispatcher would, without the full dispatch roundtrip. Existing call-sites are unaffected \u2014 the param is optional and append-only."
|
|
32
38
|
}
|
|
33
39
|
]
|
package/src/tenant/constants.ts
CHANGED
|
@@ -23,7 +23,7 @@ export const MEMBER_STATUS_CELL_COMPONENT = "MemberStatusCell" as const;
|
|
|
23
23
|
export const MEMBER_ROLES_CELL_COMPONENT = "MemberRolesCell" as const;
|
|
24
24
|
|
|
25
25
|
/** Closed allowlist for invite-role picker — never free text (escalation guard). */
|
|
26
|
-
export const DEFAULT_INVITE_ROLE_OPTIONS = ["User", "Admin", "
|
|
26
|
+
export const DEFAULT_INVITE_ROLE_OPTIONS = ["User", "Editor", "Admin", "TenantAdmin"] as const;
|
|
27
27
|
|
|
28
28
|
// Qualified write handler names (QN format: scope:type:name)
|
|
29
29
|
export const TenantHandlers = {
|
package/src/tenant/i18n.ts
CHANGED
|
@@ -28,11 +28,13 @@ export const TENANT_I18N: Readonly<Record<string, LocalizedString>> = {
|
|
|
28
28
|
"tenant:entity:__action-form__:field:role": { en: "Role" },
|
|
29
29
|
"tenant:entity:__action-form__:field:role:option:User": { en: "User" },
|
|
30
30
|
"tenant:entity:__action-form__:field:role:option:Admin": { en: "Admin" },
|
|
31
|
+
"tenant:entity:__action-form__:field:role:option:TenantAdmin": { en: "TenantAdmin" },
|
|
31
32
|
"tenant:entity:__action-form__:field:role:option:Editor": { en: "Editor" },
|
|
32
33
|
"tenant:entity:__action-form__:field:userId": { en: "User ID" },
|
|
33
34
|
"tenant:entity:__action-form__:field:roles": { en: "Roles" },
|
|
34
35
|
"tenant:entity:__action-form__:field:roles:option:User": { en: "User" },
|
|
35
36
|
"tenant:entity:__action-form__:field:roles:option:Admin": { en: "Admin" },
|
|
37
|
+
"tenant:entity:__action-form__:field:roles:option:TenantAdmin": { en: "TenantAdmin" },
|
|
36
38
|
"tenant:entity:__action-form__:field:roles:option:Editor": { en: "Editor" },
|
|
37
39
|
"tenant:entity:tenant:field:key": { en: "Key" },
|
|
38
40
|
"tenant:entity:tenant:field:name": { en: "Name" },
|