@cosmicdrift/kumiko-types 0.409.0 → 0.410.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.
@@ -0,0 +1,4 @@
1
+ import type { AccessRule } from "./handlers.ts";
2
+ export declare function isOpenToAllGranted(rule: AccessRule): boolean;
3
+ export declare function isUiAccessGranted(access: AccessRule | undefined, userRoles: readonly string[] | undefined): boolean;
4
+ export declare function isAnySignedInGranted(rule: AccessRule): boolean;
@@ -0,0 +1,42 @@
1
+ // AccessRule can arrive from untyped sources (pattern-library JSON, Designer)
2
+ // where `openToAll` doesn't actually match the declared union — narrow via
3
+ // `unknown` instead of trusting the static type, deny on anything malformed.
4
+ export function isOpenToAllGranted(rule) {
5
+ if (!("openToAll" in rule))
6
+ return false;
7
+ const openToAll = rule.openToAll;
8
+ if (typeof openToAll !== "object" || openToAll === null)
9
+ return false;
10
+ if (!("reason" in openToAll) || typeof openToAll.reason !== "string")
11
+ return false;
12
+ return openToAll.reason.trim().length > 0;
13
+ }
14
+ const ANONYMOUS_ACCESS_ROLE = "anonymous";
15
+ // UI-visibility predicate — DEFAULT-VISIBLE, the opposite stance from
16
+ // `hasAccess` and the default-deny doc on AccessRule (handlers.ts): an unset `access`
17
+ // means every signed-in user may see the screen/nav/workspace, not nobody.
18
+ // The engine's dispatcher access check stays default-deny; this only
19
+ // decides what a client renders/lists, never what a handler accepts.
20
+ // Same `unknown`-narrowing caution as isOpenToAllGranted — `access` can
21
+ // arrive from untyped sources.
22
+ export function isUiAccessGranted(access, userRoles) {
23
+ if (access === undefined)
24
+ return true;
25
+ if ("openToAll" in access)
26
+ return isOpenToAllGranted(access);
27
+ if (userRoles === undefined)
28
+ return false;
29
+ if (!("roles" in access))
30
+ return false;
31
+ if (isAnySignedInGranted(access) && !userRoles.includes(ANONYMOUS_ACCESS_ROLE))
32
+ return true;
33
+ return access.roles.some((role) => userRoles.includes(role));
34
+ }
35
+ // Same `unknown`-narrowing caution as isOpenToAllGranted. Only granted next to the
36
+ // anonymous role, so a rule can never become "every signed-in user" through this flag.
37
+ export function isAnySignedInGranted(rule) {
38
+ if (!("roles" in rule) || !("anySignedIn" in rule))
39
+ return false;
40
+ const anySignedIn = rule.anySignedIn;
41
+ return (anySignedIn === true && Array.isArray(rule.roles) && rule.roles.includes(ANONYMOUS_ACCESS_ROLE));
42
+ }
@@ -33,6 +33,7 @@ export type RoleAccessPersonalData = "public-intake";
33
33
  export type RoleAccessRule = {
34
34
  readonly roles: readonly string[];
35
35
  readonly personalData?: RoleAccessPersonalData;
36
+ readonly anySignedIn?: true;
36
37
  };
37
38
  export type AccessRule = RoleAccessRule | OpenToAllAccessRule;
38
39
  export declare const ESCAPE_HATCH_GRANTS: readonly ["systemIdentity", "globalWrites", "unsafeRaw", "crossTenantReads"];
@@ -48,8 +49,7 @@ export declare function crossTenantReadsGrantFor(declaration: EscapeHatchDeclara
48
49
  export declare function escapeHatchGrantsProblem(declaration: {
49
50
  readonly grants?: unknown;
50
51
  }): string | undefined;
51
- export declare function isOpenToAllGranted(rule: AccessRule): boolean;
52
- export declare function isUiAccessGranted(access: AccessRule | undefined, userRoles: readonly string[] | undefined): boolean;
52
+ export { isAnySignedInGranted, isOpenToAllGranted, isUiAccessGranted, } from "./access-predicates.ts";
53
53
  export type SessionUserOrigin = "member-resolution";
54
54
  export type SessionUser = {
55
55
  readonly id: string;
package/dist/handlers.js CHANGED
@@ -39,37 +39,7 @@ export function escapeHatchGrantsProblem(declaration) {
39
39
  }
40
40
  return undefined;
41
41
  }
42
- // AccessRule can arrive from untyped sources (pattern-library JSON, Designer)
43
- // where `openToAll` doesn't actually match the declared union — narrow via
44
- // `unknown` instead of trusting the static type, deny on anything malformed.
45
- export function isOpenToAllGranted(rule) {
46
- if (!("openToAll" in rule))
47
- return false;
48
- const openToAll = rule.openToAll;
49
- if (typeof openToAll !== "object" || openToAll === null)
50
- return false;
51
- if (!("reason" in openToAll) || typeof openToAll.reason !== "string")
52
- return false;
53
- return openToAll.reason.trim().length > 0;
54
- }
55
- // UI-visibility predicate — DEFAULT-VISIBLE, the opposite stance from
56
- // `hasAccess`/AccessRule's own default-deny doc above: an unset `access`
57
- // means every signed-in user may see the screen/nav/workspace, not nobody.
58
- // The engine's dispatcher access check stays default-deny; this only
59
- // decides what a client renders/lists, never what a handler accepts.
60
- // Same `unknown`-narrowing caution as isOpenToAllGranted — `access` can
61
- // arrive from untyped sources.
62
- export function isUiAccessGranted(access, userRoles) {
63
- if (access === undefined)
64
- return true;
65
- if ("openToAll" in access)
66
- return isOpenToAllGranted(access);
67
- if (userRoles === undefined)
68
- return false;
69
- if (!("roles" in access))
70
- return false;
71
- return access.roles.some((role) => userRoles.includes(role));
72
- }
42
+ export { isAnySignedInGranted, isOpenToAllGranted, isUiAccessGranted, } from "./access-predicates.js";
73
43
  // Closed vocabulary for delivery failures and skips. Only these values (plus
74
44
  // `http_<status>`) are ever stored or returned as a delivery error, never a raw
75
45
  // error message: provider errors can carry URLs, tokens and addresses.
@@ -81,10 +81,12 @@ export type ActionFormScreenDefinition = {
81
81
  * Order in the array = order in the footer, before the submit button. */
82
82
  readonly footerActions?: readonly ActionFormFooterAction[];
83
83
  /** Context box above the fields (i18n keys). `{name}` placeholders resolve from the
84
- * drawer prefill (`params` of the opening row action), formatted for display. */
84
+ * drawer prefill (`params` of the opening row action), formatted for display, and from
85
+ * the fixed `params` (e.g. the app name a feature option sets), which win on a name clash. */
85
86
  readonly summary?: {
86
87
  readonly title: string;
87
88
  readonly subtitle?: string;
89
+ readonly params?: Readonly<Record<string, string>>;
88
90
  };
89
91
  /** Visual style of the submit button. "danger" renders it red — for a form
90
92
  * whose handler is destructive (terminate, revoke, delete), so the warning
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-types",
3
- "version": "0.409.0",
3
+ "version": "0.410.0",
4
4
  "description": "Framework-Type-Definitions für Kumiko — FeatureDefinition, BootCheck-Types und die reinen Engine-Types. Erlaubt Downstream-Konsumenten, gegen die Type-Contracts zu bauen, ohne das ganze Framework-Package zu importieren. Enthaelt keine identitaets-sensitiven Runtime-Werte mehr (Error-Klassen leben seit #1629 in kumiko-framework, Brand-Symbole nutzen Symbol.for) und ist deshalb eine plain dependency, keine peerDependency.",
5
5
  "license": "MIT",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",