pi-kiosk-shared 2.1.51 → 2.1.54
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/analyticsAnonymousIdentity.d.ts +15 -0
- package/dist/analyticsAnonymousIdentity.d.ts.map +1 -0
- package/dist/analyticsAnonymousIdentity.js +38 -0
- package/dist/analyticsAnonymousIdentity.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/permissions/capabilityBridgeRules.d.ts +18 -0
- package/dist/permissions/capabilityBridgeRules.d.ts.map +1 -0
- package/dist/permissions/capabilityBridgeRules.js +83 -0
- package/dist/permissions/capabilityBridgeRules.js.map +1 -0
- package/dist/permissions/effectiveCapabilities.d.ts +5 -0
- package/dist/permissions/effectiveCapabilities.d.ts.map +1 -0
- package/dist/permissions/effectiveCapabilities.js +23 -0
- package/dist/permissions/effectiveCapabilities.js.map +1 -0
- package/dist/permissions/permissionLabels.d.ts +7 -0
- package/dist/permissions/permissionLabels.d.ts.map +1 -0
- package/dist/permissions/permissionLabels.js +29 -0
- package/dist/permissions/permissionLabels.js.map +1 -0
- package/package.json +6 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PWA pseudonymous analytics identity — client-stable opaque keys (plan §Definitions).
|
|
3
|
+
*
|
|
4
|
+
* Keys MUST NOT be derived from IP, UA, or fingerprinting. Generation uses
|
|
5
|
+
* crypto.randomUUID() only.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ANALYTICS_ANONYMOUS_KEY_MIN_LENGTH = 8;
|
|
8
|
+
export declare const ANALYTICS_ANONYMOUS_KEY_MAX_LENGTH = 128;
|
|
9
|
+
export declare const ANALYTICS_ANONYMOUS_STORAGE_KEY_PREFIX = "analytics:anonymous:";
|
|
10
|
+
/** Generate a new opaque anonymous key (UUID v4). */
|
|
11
|
+
export declare function generateAnalyticsAnonymousKey(): string;
|
|
12
|
+
/** Validate client-supplied anonymous key format (no PII-shaped values). */
|
|
13
|
+
export declare function isValidAnalyticsAnonymousKey(key: string): boolean;
|
|
14
|
+
export declare function analyticsAnonymousStorageKey(tenantCode: string): string;
|
|
15
|
+
//# sourceMappingURL=analyticsAnonymousIdentity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyticsAnonymousIdentity.d.ts","sourceRoot":"","sources":["../src/analyticsAnonymousIdentity.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,kCAAkC,IAAI,CAAC;AACpD,eAAO,MAAM,kCAAkC,MAAM,CAAC;AACtD,eAAO,MAAM,sCAAsC,yBAAyB,CAAC;AAY7E,qDAAqD;AACrD,wBAAgB,6BAA6B,IAAI,MAAM,CAKtD;AAED,4EAA4E;AAC5E,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQjE;AAED,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEvE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PWA pseudonymous analytics identity — client-stable opaque keys (plan §Definitions).
|
|
3
|
+
*
|
|
4
|
+
* Keys MUST NOT be derived from IP, UA, or fingerprinting. Generation uses
|
|
5
|
+
* crypto.randomUUID() only.
|
|
6
|
+
*/
|
|
7
|
+
export const ANALYTICS_ANONYMOUS_KEY_MIN_LENGTH = 8;
|
|
8
|
+
export const ANALYTICS_ANONYMOUS_KEY_MAX_LENGTH = 128;
|
|
9
|
+
export const ANALYTICS_ANONYMOUS_STORAGE_KEY_PREFIX = 'analytics:anonymous:';
|
|
10
|
+
const ANONYMOUS_KEY_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
11
|
+
function uuidv4Fallback() {
|
|
12
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
13
|
+
const r = Math.floor(Math.random() * 16);
|
|
14
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
15
|
+
return v.toString(16);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/** Generate a new opaque anonymous key (UUID v4). */
|
|
19
|
+
export function generateAnalyticsAnonymousKey() {
|
|
20
|
+
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
21
|
+
return crypto.randomUUID();
|
|
22
|
+
}
|
|
23
|
+
return uuidv4Fallback();
|
|
24
|
+
}
|
|
25
|
+
/** Validate client-supplied anonymous key format (no PII-shaped values). */
|
|
26
|
+
export function isValidAnalyticsAnonymousKey(key) {
|
|
27
|
+
if (key.length < ANALYTICS_ANONYMOUS_KEY_MIN_LENGTH) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
if (key.length > ANALYTICS_ANONYMOUS_KEY_MAX_LENGTH) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
return ANONYMOUS_KEY_PATTERN.test(key);
|
|
34
|
+
}
|
|
35
|
+
export function analyticsAnonymousStorageKey(tenantCode) {
|
|
36
|
+
return `${ANALYTICS_ANONYMOUS_STORAGE_KEY_PREFIX}${tenantCode}`;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=analyticsAnonymousIdentity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyticsAnonymousIdentity.js","sourceRoot":"","sources":["../src/analyticsAnonymousIdentity.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,kCAAkC,GAAG,GAAG,CAAC;AACtD,MAAM,CAAC,MAAM,sCAAsC,GAAG,sBAAsB,CAAC;AAE7E,MAAM,qBAAqB,GAAG,kBAAkB,CAAC;AAEjD,SAAS,cAAc;IACrB,OAAO,sCAAsC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;QACnE,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACzC,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;QAC1C,OAAO,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,6BAA6B;IAC3C,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;QAC7E,OAAO,MAAM,CAAC,UAAU,EAAE,CAAC;IAC7B,CAAC;IACD,OAAO,cAAc,EAAE,CAAC;AAC1B,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,4BAA4B,CAAC,GAAW;IACtD,IAAI,GAAG,CAAC,MAAM,GAAG,kCAAkC,EAAE,CAAC;QACpD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,GAAG,kCAAkC,EAAE,CAAC;QACpD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,UAAkB;IAC7D,OAAO,GAAG,sCAAsC,GAAG,UAAU,EAAE,CAAC;AAClE,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export * from './hooks/useDatabaseHealth.js';
|
|
|
18
18
|
export * from './analyticsEvents.js';
|
|
19
19
|
export * from './analyticsExploreCaps.js';
|
|
20
20
|
export * from './analyticsApiTypes.js';
|
|
21
|
+
export * from './analyticsAnonymousIdentity.js';
|
|
21
22
|
export * from './auditEventCodes.js';
|
|
22
23
|
export * from './auditEventLabels.js';
|
|
23
24
|
export * from './analyticsEventLabels.js';
|
|
@@ -32,4 +33,7 @@ export * from './complianceDevCaps.js';
|
|
|
32
33
|
export * from './customerFailureRecovery.js';
|
|
33
34
|
export * from './labels/localizedLabel.js';
|
|
34
35
|
export * from './clientLogRedaction.js';
|
|
36
|
+
export { PERMISSION_DOMAIN_LABELS, PERMISSION_LEVEL_LABELS, getPermissionDomainLabel, getPermissionLevelLabel, } from './permissions/permissionLabels.js';
|
|
37
|
+
export { expandCapabilitiesForClientCheck, grantImpliesTarget, hasEffectiveCapability, hasAnyEffectiveCapability, ADMIN_USERS_MANAGE_BRIDGE_SOURCES, ADMIN_USERS_MANAGE_BRIDGE_TARGETS, BRIDGE_PARITY_FIXTURE_GRANTS, BRIDGE_PARITY_FIXTURE_EXPECTED_TARGETS, } from './permissions/effectiveCapabilities.js';
|
|
38
|
+
export type { PermissionLevel } from './permissions/permissionLabels.js';
|
|
35
39
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,qCAAqC,CAAC;AACpD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,qCAAqC,CAAC;AACpD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,iCAAiC,CAAC;AAChD,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,gCAAgC,EAChC,kBAAkB,EAClB,sBAAsB,EACtB,yBAAyB,EACzB,iCAAiC,EACjC,iCAAiC,EACjC,4BAA4B,EAC5B,sCAAsC,GACvC,MAAM,wCAAwC,CAAC;AAChD,YAAY,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ export * from './hooks/useDatabaseHealth.js';
|
|
|
18
18
|
export * from './analyticsEvents.js';
|
|
19
19
|
export * from './analyticsExploreCaps.js';
|
|
20
20
|
export * from './analyticsApiTypes.js';
|
|
21
|
+
export * from './analyticsAnonymousIdentity.js';
|
|
21
22
|
export * from './auditEventCodes.js';
|
|
22
23
|
export * from './auditEventLabels.js';
|
|
23
24
|
export * from './analyticsEventLabels.js';
|
|
@@ -32,4 +33,6 @@ export * from './complianceDevCaps.js';
|
|
|
32
33
|
export * from './customerFailureRecovery.js';
|
|
33
34
|
export * from './labels/localizedLabel.js';
|
|
34
35
|
export * from './clientLogRedaction.js';
|
|
36
|
+
export { PERMISSION_DOMAIN_LABELS, PERMISSION_LEVEL_LABELS, getPermissionDomainLabel, getPermissionLevelLabel, } from './permissions/permissionLabels.js';
|
|
37
|
+
export { expandCapabilitiesForClientCheck, grantImpliesTarget, hasEffectiveCapability, hasAnyEffectiveCapability, ADMIN_USERS_MANAGE_BRIDGE_SOURCES, ADMIN_USERS_MANAGE_BRIDGE_TARGETS, BRIDGE_PARITY_FIXTURE_GRANTS, BRIDGE_PARITY_FIXTURE_EXPECTED_TARGETS, } from './permissions/effectiveCapabilities.js';
|
|
35
38
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,qCAAqC,CAAC;AACpD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,qCAAqC,CAAC;AACpD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,iCAAiC,CAAC;AAChD,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,gCAAgC,EAChC,kBAAkB,EAClB,sBAAsB,EACtB,yBAAyB,EACzB,iCAAiC,EACjC,iCAAiC,EACjC,4BAA4B,EAC5B,sCAAsC,GACvC,MAAM,wCAAwC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared capability bridge rules — single source for client JWT fallback checks.
|
|
3
|
+
* Server uses the same helpers from pi-kiosk-shared in PermissionInheritanceResolver.
|
|
4
|
+
*/
|
|
5
|
+
export declare const ADMIN_USERS_MANAGE_BRIDGE_SOURCES: readonly string[];
|
|
6
|
+
export declare const ADMIN_USERS_MANAGE_BRIDGE_TARGETS: readonly string[];
|
|
7
|
+
/**
|
|
8
|
+
* Forward-only implication used by client expansion and server bridge checks.
|
|
9
|
+
*/
|
|
10
|
+
export declare function grantImpliesTarget(granted: string, target: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Expands grants with bridge rules and manage→view / manage→read (no reverse implications).
|
|
13
|
+
*/
|
|
14
|
+
export declare function expandCapabilitiesForClientCheck(grants: readonly string[]): Set<string>;
|
|
15
|
+
/** Parity fixture — both backend and shared tests must satisfy. */
|
|
16
|
+
export declare const BRIDGE_PARITY_FIXTURE_GRANTS: readonly ["users:admins:create"];
|
|
17
|
+
export declare const BRIDGE_PARITY_FIXTURE_EXPECTED_TARGETS: readonly ["tenant.adminUserCapabilities.view", "tenant.adminUserCapabilities.manage", "tenant.adminUsers.manage"];
|
|
18
|
+
//# sourceMappingURL=capabilityBridgeRules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilityBridgeRules.d.ts","sourceRoot":"","sources":["../../src/permissions/capabilityBridgeRules.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,iCAAiC,EAAE,SAAS,MAAM,EAG9D,CAAC;AAEF,eAAO,MAAM,iCAAiC,EAAE,SAAS,MAAM,EAM9D,CAAC;AAIF;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAsB3E;AAmBD;;GAEG;AACH,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAkBvF;AAED,mEAAmE;AACnE,eAAO,MAAM,4BAA4B,kCAAmC,CAAC;AAE7E,eAAO,MAAM,sCAAsC,mHAIzC,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared capability bridge rules — single source for client JWT fallback checks.
|
|
3
|
+
* Server uses the same helpers from pi-kiosk-shared in PermissionInheritanceResolver.
|
|
4
|
+
*/
|
|
5
|
+
export const ADMIN_USERS_MANAGE_BRIDGE_SOURCES = [
|
|
6
|
+
'users:admins:create',
|
|
7
|
+
'tenant.adminUsers.manage',
|
|
8
|
+
];
|
|
9
|
+
export const ADMIN_USERS_MANAGE_BRIDGE_TARGETS = [
|
|
10
|
+
'users:admins:create',
|
|
11
|
+
'tenant.adminUsers.manage',
|
|
12
|
+
'tenant.adminUsers.view',
|
|
13
|
+
'tenant.adminUserCapabilities.view',
|
|
14
|
+
'tenant.adminUserCapabilities.manage',
|
|
15
|
+
];
|
|
16
|
+
const BRIDGE_SOURCE_SET = new Set(ADMIN_USERS_MANAGE_BRIDGE_SOURCES);
|
|
17
|
+
/**
|
|
18
|
+
* Forward-only implication used by client expansion and server bridge checks.
|
|
19
|
+
*/
|
|
20
|
+
export function grantImpliesTarget(granted, target) {
|
|
21
|
+
if (granted === target) {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
if (BRIDGE_SOURCE_SET.has(granted) && ADMIN_USERS_MANAGE_BRIDGE_TARGETS.includes(target)) {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
if (granted.endsWith('.manage') && target === `${granted.slice(0, -'.manage'.length)}.view`) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
if (granted.endsWith(':manage') && target === granted.replace(/:manage$/, ':read')) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
if (granted.endsWith(':write') && target === granted.replace(/:write$/, ':read')) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
function impliedTargetsFromGrant(grant) {
|
|
39
|
+
const implied = [];
|
|
40
|
+
for (const target of ADMIN_USERS_MANAGE_BRIDGE_TARGETS) {
|
|
41
|
+
if (grantImpliesTarget(grant, target)) {
|
|
42
|
+
implied.push(target);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (grant.endsWith(':manage')) {
|
|
46
|
+
implied.push(grant.replace(/:manage$/, ':read'));
|
|
47
|
+
}
|
|
48
|
+
else if (grant.endsWith(':write')) {
|
|
49
|
+
implied.push(grant.replace(/:write$/, ':read'));
|
|
50
|
+
}
|
|
51
|
+
else if (grant.endsWith('.manage')) {
|
|
52
|
+
implied.push(`${grant.slice(0, -'.manage'.length)}.view`);
|
|
53
|
+
}
|
|
54
|
+
return implied;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Expands grants with bridge rules and manage→view / manage→read (no reverse implications).
|
|
58
|
+
*/
|
|
59
|
+
export function expandCapabilitiesForClientCheck(grants) {
|
|
60
|
+
const result = new Set();
|
|
61
|
+
const pending = [...grants];
|
|
62
|
+
while (pending.length > 0) {
|
|
63
|
+
const grant = pending.pop();
|
|
64
|
+
if (grant === undefined || result.has(grant)) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
result.add(grant);
|
|
68
|
+
for (const target of impliedTargetsFromGrant(grant)) {
|
|
69
|
+
if (!result.has(target)) {
|
|
70
|
+
pending.push(target);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
/** Parity fixture — both backend and shared tests must satisfy. */
|
|
77
|
+
export const BRIDGE_PARITY_FIXTURE_GRANTS = ['users:admins:create'];
|
|
78
|
+
export const BRIDGE_PARITY_FIXTURE_EXPECTED_TARGETS = [
|
|
79
|
+
'tenant.adminUserCapabilities.view',
|
|
80
|
+
'tenant.adminUserCapabilities.manage',
|
|
81
|
+
'tenant.adminUsers.manage',
|
|
82
|
+
];
|
|
83
|
+
//# sourceMappingURL=capabilityBridgeRules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilityBridgeRules.js","sourceRoot":"","sources":["../../src/permissions/capabilityBridgeRules.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { expandCapabilitiesForClientCheck } from './capabilityBridgeRules.js';
|
|
2
|
+
export { ADMIN_USERS_MANAGE_BRIDGE_SOURCES, ADMIN_USERS_MANAGE_BRIDGE_TARGETS, BRIDGE_PARITY_FIXTURE_EXPECTED_TARGETS, BRIDGE_PARITY_FIXTURE_GRANTS, grantImpliesTarget, } from './capabilityBridgeRules.js';
|
|
3
|
+
export declare function hasEffectiveCapability(grants: readonly string[], required: string): boolean;
|
|
4
|
+
export declare function hasAnyEffectiveCapability(grants: readonly string[], required: readonly string[]): boolean;
|
|
5
|
+
//# sourceMappingURL=effectiveCapabilities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effectiveCapabilities.d.ts","sourceRoot":"","sources":["../../src/permissions/effectiveCapabilities.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,gCAAgC,EAAE,MAAM,4BAA4B,CAAC;AAE9E,OAAO,EACL,iCAAiC,EACjC,iCAAiC,EACjC,sCAAsC,EACtC,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AAEpC,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,QAAQ,EAAE,MAAM,GACf,OAAO,CAWT;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,QAAQ,EAAE,SAAS,MAAM,EAAE,GAC1B,OAAO,CAET"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side effective capability checks — mirrors server JWT expansion for UI gates.
|
|
3
|
+
* Prefer capabilities from GET /admin/me (server-expanded); use this as fallback only.
|
|
4
|
+
*/
|
|
5
|
+
import { expandCapabilitiesForClientCheck, grantImpliesTarget, } from './capabilityBridgeRules.js';
|
|
6
|
+
export { expandCapabilitiesForClientCheck } from './capabilityBridgeRules.js';
|
|
7
|
+
export { ADMIN_USERS_MANAGE_BRIDGE_SOURCES, ADMIN_USERS_MANAGE_BRIDGE_TARGETS, BRIDGE_PARITY_FIXTURE_EXPECTED_TARGETS, BRIDGE_PARITY_FIXTURE_GRANTS, grantImpliesTarget, } from './capabilityBridgeRules.js';
|
|
8
|
+
export function hasEffectiveCapability(grants, required) {
|
|
9
|
+
const expanded = expandCapabilitiesForClientCheck(grants);
|
|
10
|
+
if (expanded.has(required)) {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
for (const grant of expanded) {
|
|
14
|
+
if (grantImpliesTarget(grant, required)) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
export function hasAnyEffectiveCapability(grants, required) {
|
|
21
|
+
return required.some((cap) => hasEffectiveCapability(grants, cap));
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=effectiveCapabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effectiveCapabilities.js","sourceRoot":"","sources":["../../src/permissions/effectiveCapabilities.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,gCAAgC,EAChC,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,gCAAgC,EAAE,MAAM,4BAA4B,CAAC;AAE9E,OAAO,EACL,iCAAiC,EACjC,iCAAiC,EACjC,sCAAsC,EACtC,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,UAAU,sBAAsB,CACpC,MAAyB,EACzB,QAAgB;IAEhB,MAAM,QAAQ,GAAG,gCAAgC,CAAC,MAAM,CAAC,CAAC;IAC1D,IAAI,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,kBAAkB,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC;YACxC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,MAAyB,EACzB,QAA2B;IAE3B,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,sBAAsB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;AACrE,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { LabelLocale, LocalizedLabel } from '../labels/localizedLabel.js';
|
|
2
|
+
export type PermissionLevel = 'view' | 'manage';
|
|
3
|
+
export declare const PERMISSION_LEVEL_LABELS: Record<PermissionLevel, LocalizedLabel>;
|
|
4
|
+
export declare const PERMISSION_DOMAIN_LABELS: Record<string, LocalizedLabel>;
|
|
5
|
+
export declare function getPermissionLevelLabel(level: PermissionLevel, locale: LabelLocale): string;
|
|
6
|
+
export declare function getPermissionDomainLabel(domain: string, locale: LabelLocale): string;
|
|
7
|
+
//# sourceMappingURL=permissionLabels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissionLabels.d.ts","sourceRoot":"","sources":["../../src/permissions/permissionLabels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE/E,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEhD,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,eAAe,EAAE,cAAc,CAG3E,CAAC;AAEF,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAQnE,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CAE3F;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CAWpF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export const PERMISSION_LEVEL_LABELS = {
|
|
2
|
+
view: { en: 'View', cs: 'Zobrazení' },
|
|
3
|
+
manage: { en: 'Manage', cs: 'Správa' },
|
|
4
|
+
};
|
|
5
|
+
export const PERMISSION_DOMAIN_LABELS = {
|
|
6
|
+
principal: { en: 'Account access', cs: 'Přístup k účtu' },
|
|
7
|
+
account: { en: 'Account', cs: 'Účet' },
|
|
8
|
+
permissions: { en: 'Permissions catalog', cs: 'Katalog oprávnění' },
|
|
9
|
+
tenant: { en: 'Tenant operations', cs: 'Provoz tenantu' },
|
|
10
|
+
platform: { en: 'Platform administration', cs: 'Správa platformy' },
|
|
11
|
+
exceptions: { en: 'High-risk exceptions', cs: 'Vysoce rizikové výjimky' },
|
|
12
|
+
compliance: { en: 'Compliance', cs: 'Compliance' },
|
|
13
|
+
};
|
|
14
|
+
export function getPermissionLevelLabel(level, locale) {
|
|
15
|
+
return PERMISSION_LEVEL_LABELS[level][locale];
|
|
16
|
+
}
|
|
17
|
+
export function getPermissionDomainLabel(domain, locale) {
|
|
18
|
+
const known = PERMISSION_DOMAIN_LABELS[domain];
|
|
19
|
+
if (known !== undefined) {
|
|
20
|
+
return known[locale];
|
|
21
|
+
}
|
|
22
|
+
const fallback = domain
|
|
23
|
+
.split(/[._-]/)
|
|
24
|
+
.filter(Boolean)
|
|
25
|
+
.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
|
|
26
|
+
.join(' ');
|
|
27
|
+
return fallback.length > 0 ? fallback : 'Permissions';
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=permissionLabels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissionLabels.js","sourceRoot":"","sources":["../../src/permissions/permissionLabels.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,uBAAuB,GAA4C;IAC9E,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE;IACrC,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE;CACvC,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAmC;IACtE,SAAS,EAAE,EAAE,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE,gBAAgB,EAAE;IACzD,OAAO,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE;IACtC,WAAW,EAAE,EAAE,EAAE,EAAE,qBAAqB,EAAE,EAAE,EAAE,mBAAmB,EAAE;IACnE,MAAM,EAAE,EAAE,EAAE,EAAE,mBAAmB,EAAE,EAAE,EAAE,gBAAgB,EAAE;IACzD,QAAQ,EAAE,EAAE,EAAE,EAAE,yBAAyB,EAAE,EAAE,EAAE,kBAAkB,EAAE;IACnE,UAAU,EAAE,EAAE,EAAE,EAAE,sBAAsB,EAAE,EAAE,EAAE,yBAAyB,EAAE;IACzE,UAAU,EAAE,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,YAAY,EAAE;CACnD,CAAC;AAEF,MAAM,UAAU,uBAAuB,CAAC,KAAsB,EAAE,MAAmB;IACjF,OAAO,uBAAuB,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,MAAc,EAAE,MAAmB;IAC1E,MAAM,KAAK,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAC/C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM;SACpB,KAAK,CAAC,OAAO,CAAC;SACd,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SACpE,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC;AACxD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-kiosk-shared",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.54",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Shared types, API contracts, and error classes for Pi Kiosk system",
|
|
@@ -60,6 +60,11 @@
|
|
|
60
60
|
"require": "./dist/analyticsConsentAllowlist.js",
|
|
61
61
|
"types": "./dist/analyticsConsentAllowlist.d.ts"
|
|
62
62
|
},
|
|
63
|
+
"./analyticsAnonymousIdentity": {
|
|
64
|
+
"import": "./dist/analyticsAnonymousIdentity.js",
|
|
65
|
+
"require": "./dist/analyticsAnonymousIdentity.js",
|
|
66
|
+
"types": "./dist/analyticsAnonymousIdentity.d.ts"
|
|
67
|
+
},
|
|
63
68
|
"./clientLogRedaction": {
|
|
64
69
|
"import": "./dist/clientLogRedaction.js",
|
|
65
70
|
"require": "./dist/clientLogRedaction.js",
|