@almadar/runtime 6.45.0 → 6.47.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.
|
@@ -1348,6 +1348,15 @@ declare class OrbitalServerRuntime {
|
|
|
1348
1348
|
setDefaultUser(user: UserContext | undefined): void;
|
|
1349
1349
|
/** The viewer a dev host is currently presenting the app as. */
|
|
1350
1350
|
getDefaultUser(): UserContext | undefined;
|
|
1351
|
+
/**
|
|
1352
|
+
* The registered app's declared persona roster: the live rows of its
|
|
1353
|
+
* `[identity]` entity, mapped onto viewers (`Almadar_LOLO_Identity.md` §4.3).
|
|
1354
|
+
* Live-store rows rather than a re-derivation, so the roster carries the ids
|
|
1355
|
+
* ownership scoping actually compares `@user.id` against. Empty when no
|
|
1356
|
+
* schema is registered or the app declares no `[identity]` entity — there is
|
|
1357
|
+
* no global fallback roster by design.
|
|
1358
|
+
*/
|
|
1359
|
+
getIdentityRoster(): Promise<UserContext[]>;
|
|
1351
1360
|
/**
|
|
1352
1361
|
* `traitFieldStates` key for one trait: its own name, or — when its linked
|
|
1353
1362
|
* entity is `[shared]` — `$shared::<entityName>` so every trait bound to
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import 'express';
|
|
2
|
-
export { F as ClientEffectTuple, G as ClientNavigateTuple, H as ClientNotifyTuple, J as ClientRenderUITuple, K as EffectResult, e as InMemoryPersistence, M as LiveBroadcastItem, N as LoaderConfig, O as OrbitalEventRequest, f as OrbitalEventResponse, Q as OrbitalServerRuntime, g as OrbitalServerRuntimeConfig, P as PersistenceAdapter, R as RegisteredOrbital, l as RuntimeOrbital, m as RuntimeOrbitalSchema, n as RuntimeTrait, T as RuntimeTraitTick, p as collectDeclaredConfigDefaults, V as createOrbitalServerRuntime } from './OrbitalServerRuntime-
|
|
2
|
+
export { F as ClientEffectTuple, G as ClientNavigateTuple, H as ClientNotifyTuple, J as ClientRenderUITuple, K as EffectResult, e as InMemoryPersistence, M as LiveBroadcastItem, N as LoaderConfig, O as OrbitalEventRequest, f as OrbitalEventResponse, Q as OrbitalServerRuntime, g as OrbitalServerRuntimeConfig, P as PersistenceAdapter, R as RegisteredOrbital, l as RuntimeOrbital, m as RuntimeOrbitalSchema, n as RuntimeTrait, T as RuntimeTraitTick, p as collectDeclaredConfigDefaults, V as createOrbitalServerRuntime } from './OrbitalServerRuntime-e-5490xl.js';
|
|
3
3
|
import './types-CL03tjGU.js';
|
|
4
4
|
import '@almadar/core';
|
|
@@ -7,8 +7,8 @@ import './chunk-MLKGABMK.js';
|
|
|
7
7
|
import { createLogger } from '@almadar/logger';
|
|
8
8
|
import * as nodeModule from 'module';
|
|
9
9
|
import { evaluateListenPayloadExpr, evaluateGuard, evaluate } from '@almadar/evaluator';
|
|
10
|
-
import { DEFAULT_VIEWER, buildResolvedTraitConfigs, isInlineTrait, isEntityCall, applyListenPayloadMapping, normalizeUserContext, isRuntimeEntity } from '@almadar/core';
|
|
11
|
-
import { ownerFieldsFromSchema, identityEntityName } from '@almadar/core/mock';
|
|
10
|
+
import { DEFAULT_VIEWER, buildResolvedTraitConfigs, isInlineTrait, isEntityCall, applyListenPayloadMapping, personaFromIdentityRow, normalizeUserContext, isRuntimeEntity } from '@almadar/core';
|
|
11
|
+
import { ownerFieldsFromSchema, identityEntityName, entityAccessPolicies } from '@almadar/core/mock';
|
|
12
12
|
|
|
13
13
|
// src/identity/routing.ts
|
|
14
14
|
function eventRouteKey(eventName, eventId) {
|
|
@@ -33,6 +33,41 @@ function buildSourceMatcher(src, listenerOrbital) {
|
|
|
33
33
|
const wantedTrait = src.trait;
|
|
34
34
|
return (source) => !!source && source.orbital === wantedOrbital && source.trait === wantedTrait;
|
|
35
35
|
}
|
|
36
|
+
function applyRowAccess(rows, policy, filter, bindings) {
|
|
37
|
+
if (policy === void 0 && filter === void 0) {
|
|
38
|
+
return rows;
|
|
39
|
+
}
|
|
40
|
+
const predicates = [policy, filter].filter((p) => p !== void 0);
|
|
41
|
+
return rows.filter((entity) => {
|
|
42
|
+
const ctx = createContextFromBindings(
|
|
43
|
+
{ entity, payload: bindings.payload, current: entity, user: bindings.user, config: bindings.config },
|
|
44
|
+
false
|
|
45
|
+
);
|
|
46
|
+
return predicates.every((predicate) => {
|
|
47
|
+
try {
|
|
48
|
+
return Boolean(evaluate(predicate, ctx));
|
|
49
|
+
} catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function checkMutationAccess(row, policy, bindings) {
|
|
56
|
+
if (policy === void 0) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
const ctx = createContextFromBindings(
|
|
60
|
+
{ entity: row, payload: bindings.payload, current: row, user: bindings.user, config: bindings.config },
|
|
61
|
+
false
|
|
62
|
+
);
|
|
63
|
+
try {
|
|
64
|
+
return Boolean(evaluate(policy, ctx));
|
|
65
|
+
} catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// src/OrbitalServerRuntime.ts
|
|
36
71
|
var _resolvedNodeRequire = null;
|
|
37
72
|
function nodeRequire(modulePath) {
|
|
38
73
|
if (!_resolvedNodeRequire) {
|
|
@@ -922,6 +957,22 @@ var OrbitalServerRuntime = class {
|
|
|
922
957
|
getDefaultUser() {
|
|
923
958
|
return this.config.defaultUser;
|
|
924
959
|
}
|
|
960
|
+
/**
|
|
961
|
+
* The registered app's declared persona roster: the live rows of its
|
|
962
|
+
* `[identity]` entity, mapped onto viewers (`Almadar_LOLO_Identity.md` §4.3).
|
|
963
|
+
* Live-store rows rather than a re-derivation, so the roster carries the ids
|
|
964
|
+
* ownership scoping actually compares `@user.id` against. Empty when no
|
|
965
|
+
* schema is registered or the app declares no `[identity]` entity — there is
|
|
966
|
+
* no global fallback roster by design.
|
|
967
|
+
*/
|
|
968
|
+
async getIdentityRoster() {
|
|
969
|
+
const schema = this.resolvedSchema;
|
|
970
|
+
if (!schema) return [];
|
|
971
|
+
const entityName = identityEntityName(schema);
|
|
972
|
+
if (!entityName) return [];
|
|
973
|
+
const rows = await this.persistence.list(entityName);
|
|
974
|
+
return rows.map((row) => personaFromIdentityRow(row)).filter((p) => p !== void 0);
|
|
975
|
+
}
|
|
925
976
|
// ==========================================================================
|
|
926
977
|
// Event Processing
|
|
927
978
|
// ==========================================================================
|
|
@@ -1134,6 +1185,15 @@ var OrbitalServerRuntime = class {
|
|
|
1134
1185
|
*/
|
|
1135
1186
|
async executeEffects(registered, traitName, effects, payload, entityData, entityId, emittedEvents, fetchedData, clientEffects, effectResults, user, clientEffectsByTrait, onPush, originClientId) {
|
|
1136
1187
|
const entityType = registered.entity.name;
|
|
1188
|
+
for (const eff of effects) {
|
|
1189
|
+
if (Array.isArray(eff) && eff[0] === "fetch") {
|
|
1190
|
+
xOrbitalLog.debug("fetch:pre-exec-keys", () => ({
|
|
1191
|
+
trait: traitName,
|
|
1192
|
+
entity: String(eff[1]),
|
|
1193
|
+
optKeys: Object.keys(eff[2] ?? {}).join("+")
|
|
1194
|
+
}));
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1137
1197
|
const pushClientEffect = (effect) => {
|
|
1138
1198
|
clientEffects.push(effect);
|
|
1139
1199
|
clientEffectsByTrait?.push({ traitName, effect });
|
|
@@ -1291,8 +1351,15 @@ var OrbitalServerRuntime = class {
|
|
|
1291
1351
|
if (action === "create" || action === "update") {
|
|
1292
1352
|
this.validateRelationCardinality(type, data || {});
|
|
1293
1353
|
}
|
|
1354
|
+
const accessBindings = { user: bindingsRef?.user, payload: bindingsRef?.payload, config: bindingsRef?.config };
|
|
1355
|
+
const mutationPolicy = this.resolvedSchema ? entityAccessPolicies(this.resolvedSchema, type)?.[action === "create" ? "create" : action === "update" ? "update" : "delete"] : void 0;
|
|
1294
1356
|
switch (action) {
|
|
1295
1357
|
case "create": {
|
|
1358
|
+
if (!checkMutationAccess(data || {}, mutationPolicy, accessBindings)) {
|
|
1359
|
+
throw new Error(
|
|
1360
|
+
`@create denied: the declared access policy for '${type}' rejected this row`
|
|
1361
|
+
);
|
|
1362
|
+
}
|
|
1296
1363
|
const { id } = await this.persistence.create(type, data || {});
|
|
1297
1364
|
resultData = { id, ...data || {} };
|
|
1298
1365
|
break;
|
|
@@ -1300,6 +1367,14 @@ var OrbitalServerRuntime = class {
|
|
|
1300
1367
|
case "update":
|
|
1301
1368
|
if (data?.id || entityId) {
|
|
1302
1369
|
const updateId = data?.id || entityId;
|
|
1370
|
+
if (mutationPolicy !== void 0) {
|
|
1371
|
+
const existing = await this.persistence.getById(type, updateId);
|
|
1372
|
+
if (!existing || !checkMutationAccess(existing, mutationPolicy, accessBindings)) {
|
|
1373
|
+
throw new Error(
|
|
1374
|
+
`@update denied: the declared access policy for '${type}' rejected this row`
|
|
1375
|
+
);
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1303
1378
|
await this.persistence.update(type, updateId, data || {});
|
|
1304
1379
|
const updated = await this.persistence.getById(type, updateId);
|
|
1305
1380
|
resultData = updated || { id: updateId, ...data || {} };
|
|
@@ -1310,6 +1385,14 @@ var OrbitalServerRuntime = class {
|
|
|
1310
1385
|
const nestedId = typeof data === "object" && data !== null ? data.id : void 0;
|
|
1311
1386
|
const deleteId = directId ?? nestedId ?? entityId;
|
|
1312
1387
|
if (deleteId) {
|
|
1388
|
+
if (mutationPolicy !== void 0) {
|
|
1389
|
+
const existing = await this.persistence.getById(type, deleteId);
|
|
1390
|
+
if (!existing || !checkMutationAccess(existing, mutationPolicy, accessBindings)) {
|
|
1391
|
+
throw new Error(
|
|
1392
|
+
`@delete denied: the declared access policy for '${type}' rejected this row`
|
|
1393
|
+
);
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1313
1396
|
await this.enforceOnDeleteRules(type, deleteId);
|
|
1314
1397
|
await this.persistence.delete(type, deleteId);
|
|
1315
1398
|
resultData = { id: deleteId, deleted: true };
|
|
@@ -1396,20 +1479,13 @@ var OrbitalServerRuntime = class {
|
|
|
1396
1479
|
},
|
|
1397
1480
|
fetch: async (fetchEntityType, options) => {
|
|
1398
1481
|
try {
|
|
1399
|
-
xOrbitalLog.info("fetch:enter", () => ({
|
|
1400
|
-
entityType: fetchEntityType,
|
|
1401
|
-
hasOptions: options !== void 0 && options !== null,
|
|
1402
|
-
optionsKeys: options ? Object.keys(options).join(",") : "",
|
|
1403
|
-
filterType: typeof options?.filter,
|
|
1404
|
-
filterIsArray: Array.isArray(options?.filter),
|
|
1405
|
-
filterJson: JSON.stringify(options?.filter ?? null).slice(0, 300),
|
|
1406
|
-
payloadJson: JSON.stringify(bindingsRef?.payload ?? null).slice(0, 300)
|
|
1407
|
-
}));
|
|
1408
1482
|
let result = null;
|
|
1409
1483
|
let total = 0;
|
|
1484
|
+
const readPolicy = this.resolvedSchema ? entityAccessPolicies(this.resolvedSchema, fetchEntityType)?.read : void 0;
|
|
1485
|
+
const accessBindings = { user: bindingsRef?.user, payload: bindingsRef?.payload, config: bindingsRef?.config };
|
|
1410
1486
|
if (options?.id) {
|
|
1411
1487
|
const entity = await this.persistence.getById(fetchEntityType, options.id);
|
|
1412
|
-
if (entity) {
|
|
1488
|
+
if (entity && applyRowAccess([entity], readPolicy, void 0, accessBindings).length > 0) {
|
|
1413
1489
|
if (options?.include && options.include.length > 0) {
|
|
1414
1490
|
await this.populateRelations([entity], fetchEntityType, options.include);
|
|
1415
1491
|
}
|
|
@@ -1419,24 +1495,12 @@ var OrbitalServerRuntime = class {
|
|
|
1419
1495
|
}
|
|
1420
1496
|
} else {
|
|
1421
1497
|
let entities = await this.persistence.list(fetchEntityType);
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
);
|
|
1429
|
-
try {
|
|
1430
|
-
return Boolean(evaluate(predicate, ctx));
|
|
1431
|
-
} catch (err) {
|
|
1432
|
-
effectLog.error("fetch:filter-eval-error", {
|
|
1433
|
-
entityType: fetchEntityType,
|
|
1434
|
-
error: err instanceof Error ? err : String(err)
|
|
1435
|
-
});
|
|
1436
|
-
return false;
|
|
1437
|
-
}
|
|
1438
|
-
});
|
|
1439
|
-
}
|
|
1498
|
+
entities = applyRowAccess(
|
|
1499
|
+
entities,
|
|
1500
|
+
readPolicy,
|
|
1501
|
+
options?.filter !== void 0 && options.filter !== null ? options.filter : void 0,
|
|
1502
|
+
accessBindings
|
|
1503
|
+
);
|
|
1440
1504
|
total = entities.length;
|
|
1441
1505
|
if (options?.offset && options.offset > 0) {
|
|
1442
1506
|
entities = entities.slice(options.offset);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { g as RuntimePatternValue, B as BindingContext, f as EvaluationContextExtensions, P as PatternProps, E as EffectHandlers, h as EffectContext, i as ExecutionEnvironment, j as EffectResult, T as TraitDefinition } from './types-CL03tjGU.js';
|
|
2
2
|
export { k as BrowserFileMeta, l as BrowserFilePickerOptions, m as BrowserGeolocationOptions, n as BrowserGeolocationPosition, C as ConfigContext, o as Effect, a as EventListener, H as HANDLER_MANIFEST, I as IEventBus, b as RuntimeConfig, R as RuntimeEvent, d as TraitState, c as TransitionObserver, e as TransitionResult, U as Unsubscribe } from './types-CL03tjGU.js';
|
|
3
|
-
import { U as UnifiedLoaderOptions, S as SchemaLoader, I as ImportChainLike, L as LoadResult, a as LoadedSchema, b as LoadedOrbital, P as PersistenceAdapter } from './OrbitalServerRuntime-
|
|
4
|
-
export { E as EntitySharingMap, c as EventBus, d as EventNamespaceMap, e as InMemoryPersistence, O as OrbitalEventRequest, f as OrbitalEventResponse, g as OrbitalServerRuntimeConfig, h as PreprocessOptions, i as PreprocessResult, j as PreprocessedSchema, k as ProcessEventOptions, R as RegisteredOrbital, l as RuntimeOrbital, m as RuntimeOrbitalSchema, n as RuntimeTrait, o as StateMachineManager, p as collectDeclaredConfigDefaults, q as collectDeclaredEntityDefaults, r as createInitialTraitState, s as findInitialState, t as findTransition, u as getIsolatedCollectionName, v as getNamespacedEvent, w as isBrowser, x as isElectron, y as isNamespacedEvent, z as isNode, A as normalizeEventKey, B as parseNamespacedEvent, C as preprocessSchema, D as processEvent } from './OrbitalServerRuntime-
|
|
3
|
+
import { U as UnifiedLoaderOptions, S as SchemaLoader, I as ImportChainLike, L as LoadResult, a as LoadedSchema, b as LoadedOrbital, P as PersistenceAdapter } from './OrbitalServerRuntime-e-5490xl.js';
|
|
4
|
+
export { E as EntitySharingMap, c as EventBus, d as EventNamespaceMap, e as InMemoryPersistence, O as OrbitalEventRequest, f as OrbitalEventResponse, g as OrbitalServerRuntimeConfig, h as PreprocessOptions, i as PreprocessResult, j as PreprocessedSchema, k as ProcessEventOptions, R as RegisteredOrbital, l as RuntimeOrbital, m as RuntimeOrbitalSchema, n as RuntimeTrait, o as StateMachineManager, p as collectDeclaredConfigDefaults, q as collectDeclaredEntityDefaults, r as createInitialTraitState, s as findInitialState, t as findTransition, u as getIsolatedCollectionName, v as getNamespacedEvent, w as isBrowser, x as isElectron, y as isNamespacedEvent, z as isNode, A as normalizeEventKey, B as parseNamespacedEvent, C as preprocessSchema, D as processEvent } from './OrbitalServerRuntime-e-5490xl.js';
|
|
5
5
|
import { EvaluationContext, SExpressionEvaluator } from '@almadar/evaluator';
|
|
6
6
|
export { EvaluationContext, createMinimalContext } from '@almadar/evaluator';
|
|
7
7
|
import { RenderBindingMarker, SExpr, TraitConfigObject, EventPayload, PatternConfig, EntityId, EntityField, EntityRow, EntityPersistence, ServiceParams, PayloadField, OrbitalDefinition, OrbitalSchema } from '@almadar/core';
|
package/dist/index.js
CHANGED
|
@@ -409,15 +409,6 @@ function createServerEffectHandlers(opts) {
|
|
|
409
409
|
},
|
|
410
410
|
fetch: async (fetchEntityType, options) => {
|
|
411
411
|
try {
|
|
412
|
-
effectLog.info("clientFetch:enter", () => ({
|
|
413
|
-
entityType: fetchEntityType,
|
|
414
|
-
hasOptions: options !== void 0 && options !== null,
|
|
415
|
-
optionsKeys: options ? Object.keys(options).join(",") : "",
|
|
416
|
-
filterType: typeof options?.filter,
|
|
417
|
-
filterIsArray: Array.isArray(options?.filter),
|
|
418
|
-
filterJson: JSON.stringify(options?.filter ?? null).slice(0, 300),
|
|
419
|
-
payloadJson: JSON.stringify(bindings?.payload ?? null).slice(0, 300)
|
|
420
|
-
}));
|
|
421
412
|
let result = null;
|
|
422
413
|
let total = 0;
|
|
423
414
|
if (options?.id) {
|
|
@@ -433,7 +424,7 @@ function createServerEffectHandlers(opts) {
|
|
|
433
424
|
const predicate = options.filter;
|
|
434
425
|
entities = entities.filter((entity) => {
|
|
435
426
|
const ctx = createContextFromBindings(
|
|
436
|
-
{ entity, payload: bindings?.payload, current: entity },
|
|
427
|
+
{ entity, payload: bindings?.payload, current: entity, user: bindings?.user, config: bindings?.config },
|
|
437
428
|
false
|
|
438
429
|
);
|
|
439
430
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@almadar/runtime",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.47.0",
|
|
4
4
|
"description": "Interpreted runtime for Almadar orbital applications (OrbitalServerRuntime)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -52,11 +52,11 @@
|
|
|
52
52
|
"access": "public"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@almadar/core": "^10.
|
|
55
|
+
"@almadar/core": "^10.45.0",
|
|
56
56
|
"@almadar/evaluator": "^2.38.0",
|
|
57
57
|
"@almadar/logger": "^1.10.0",
|
|
58
|
-
"@almadar/server": "^2.
|
|
59
|
-
"@almadar/std": "^16.
|
|
58
|
+
"@almadar/server": "^2.30.0",
|
|
59
|
+
"@almadar/std": "^16.155.0"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
62
|
"express": "^5.0.0"
|