@happyvertical/smrt-playbooks 0.44.0 → 0.45.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/AGENTS.md +93 -0
- package/dist/index.d.ts +282 -0
- package/dist/index.js +246 -3
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +1 -1
- package/dist/preflight-types.d.ts +276 -0
- package/dist/preflight-types.js +0 -0
- package/dist/smrt-knowledge.json +127 -6
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PLAYBOOK_PLANES } from "./types.js";
|
|
2
|
-
import { ObjectRegistry, SmrtCollection, SmrtObject, field, smrt } from "@happyvertical/smrt-core";
|
|
2
|
+
import { ObjectRegistry, SmrtCollection, SmrtObject, field, isApiActionEnabledForObject, isRestActionRoutable, isRestRoutePublic, resolveRegisteredObjectName, restFieldReadPermissions, restMethodForApiAction, smrt } from "@happyvertical/smrt-core";
|
|
3
3
|
import { getPackageConfig } from "@happyvertical/smrt-config";
|
|
4
4
|
import { getTenantId } from "@happyvertical/smrt-tenancy";
|
|
5
5
|
//#region \0rolldown/runtime.js
|
|
@@ -15,7 +15,7 @@ var __exportAll = (all, no_symbols) => {
|
|
|
15
15
|
};
|
|
16
16
|
//#endregion
|
|
17
17
|
//#region src/__smrt-register__.ts
|
|
18
|
-
ObjectRegistry.registerPackageManifest(JSON.parse("{\"version\":\"1.0.0\",\"timestamp\":0,\"packageName\":\"@happyvertical/smrt-playbooks\",\"packageVersion\":\"0.
|
|
18
|
+
ObjectRegistry.registerPackageManifest(JSON.parse("{\"version\":\"1.0.0\",\"timestamp\":0,\"packageName\":\"@happyvertical/smrt-playbooks\",\"packageVersion\":\"0.45.0\",\"objects\":{\"@happyvertical/smrt-playbooks:PlaybookOverrideCollection\":{\"name\":\"playbookoverridecollection\",\"className\":\"PlaybookOverrideCollection\",\"qualifiedName\":\"@happyvertical/smrt-playbooks:PlaybookOverrideCollection\",\"collection\":\"playbookoverrides\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/playbooks/src/collections/PlaybookOverrideCollection.ts\",\"packageName\":\"@happyvertical/smrt-playbooks\",\"fields\":{},\"methods\":{\"getAppOverride\":{\"name\":\"getAppOverride\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<PlaybookOverride | null>\",\"isStatic\":false,\"isPublic\":true},\"getTenantOverride\":{\"name\":\"getTenantOverride\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false},{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<PlaybookOverride | null>\",\"isStatic\":false,\"isPublic\":true},\"getResolutionLayers\":{\"name\":\"getResolutionLayers\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false},{\"name\":\"tenantId\",\"type\":\"string | null\",\"optional\":true},{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<object>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"_smrt_playbook_overrides\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"PlaybookOverride\",\"exportName\":\"PlaybookOverrideCollection\",\"collectionExportName\":\"PlaybookOverrideCollectionCollection\",\"schema\":{\"tableName\":\"_smrt_playbook_overrides\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"_smrt_playbook_overrides\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"_smrt_playbook_overrides_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"_smrt_playbook_overrides_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"410e08c4\"}},\"@happyvertical/smrt-playbooks:PlaybookOverride\":{\"name\":\"playbookoverride\",\"className\":\"PlaybookOverride\",\"qualifiedName\":\"@happyvertical/smrt-playbooks:PlaybookOverride\",\"collection\":\"playbookoverrides\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/playbooks/src/models/PlaybookOverride.ts\",\"packageName\":\"@happyvertical/smrt-playbooks\",\"fields\":{\"key\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true}},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true}},\"title\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true}},\"description\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true}},\"planes\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true}},\"onStepFailure\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true}},\"enabled\":{\"type\":\"boolean\",\"required\":false,\"_meta\":{\"nullable\":true}},\"metadata\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true}}},\"methods\":{\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"PlaybookMetadata\",\"isStatic\":false,\"isPublic\":true},\"setMetadata\":{\"name\":\"setMetadata\",\"async\":false,\"parameters\":[{\"name\":\"metadata\",\"type\":\"PlaybookMetadata | null\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"getPlanes\":{\"name\":\"getPlanes\",\"async\":false,\"parameters\":[],\"returnType\":\"null\",\"isStatic\":false,\"isPublic\":true},\"setPlanes\":{\"name\":\"setPlanes\",\"async\":false,\"parameters\":[{\"name\":\"planes\",\"type\":\"null\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"toPlaybookLayer\":{\"name\":\"toPlaybookLayer\",\"async\":false,\"parameters\":[],\"returnType\":\"PlaybookLayer\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"delete\":{\"name\":\"delete\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"_smrt_playbook_overrides\",\"conflictColumns\":[\"key\",\"context\"],\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"cli\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"],\"exclude\":[\"getMetadata\",\"setMetadata\",\"getPlanes\",\"setPlanes\",\"toPlaybookLayer\"]},\"mcp\":{\"include\":[]}},\"extends\":\"SmrtObject\",\"exportName\":\"PlaybookOverride\",\"collectionExportName\":\"PlaybookOverrideCollection\",\"validationRules\":[{\"field\":\"key\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"_smrt_playbook_overrides\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"_smrt_playbook_overrides\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"key\\\" TEXT NOT NULL DEFAULT '',\\n \\\"tenant_id\\\" TEXT,\\n \\\"title\\\" TEXT,\\n \\\"description\\\" TEXT,\\n \\\"planes\\\" TEXT,\\n \\\"on_step_failure\\\" TEXT,\\n \\\"enabled\\\" BOOLEAN,\\n \\\"metadata\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"key\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false,\"default\":\"\"},\"tenant_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"title\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"planes\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"on_step_failure\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"enabled\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"unique\":false},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"_smrt_playbook_overrides_key_context_idx\",\"columns\":[\"key\",\"context\"],\"unique\":true},{\"name\":\"_smrt_playbook_overrides_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"_smrt_playbook_overrides_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"8aec8e13\"}}},\"moduleType\":\"smrt\",\"smrtDependencies\":[\"@happyvertical/smrt-core\",\"@happyvertical/smrt-tenancy\"]}"));
|
|
19
19
|
//#endregion
|
|
20
20
|
//#region src/cache.ts
|
|
21
21
|
var PLAYBOOK_CACHE_TTL_MS = 3e4;
|
|
@@ -42,6 +42,9 @@ function getDbNamespace(db) {
|
|
|
42
42
|
}
|
|
43
43
|
return "db:unknown";
|
|
44
44
|
}
|
|
45
|
+
function playbookCacheNamespace(db) {
|
|
46
|
+
return getDbNamespace(db);
|
|
47
|
+
}
|
|
45
48
|
function buildCacheKey(key, tenantId, db) {
|
|
46
49
|
return `${getDbNamespace(db)}::${key}::${tenantId ?? "app"}`;
|
|
47
50
|
}
|
|
@@ -726,9 +729,249 @@ async function resolvePlaybook(key, options = {}) {
|
|
|
726
729
|
};
|
|
727
730
|
}
|
|
728
731
|
//#endregion
|
|
732
|
+
//#region src/preflight-cache.ts
|
|
733
|
+
var PREFLIGHT_CACHE_TTL_MS = 15e3;
|
|
734
|
+
var PREFLIGHT_CACHE_MAX_ENTRIES = 1e3;
|
|
735
|
+
var preflightCache = /* @__PURE__ */ new Map();
|
|
736
|
+
function buildKey(scope) {
|
|
737
|
+
return `${playbookCacheNamespace(scope.db)}::${scope.principal}::${scope.key}::${scope.plane}::${scope.tenantId ?? "app"}`;
|
|
738
|
+
}
|
|
739
|
+
function evict() {
|
|
740
|
+
const now = Date.now();
|
|
741
|
+
for (const [cacheKey, entry] of preflightCache) if (entry.expiresAt <= now) preflightCache.delete(cacheKey);
|
|
742
|
+
for (const cacheKey of preflightCache.keys()) {
|
|
743
|
+
if (preflightCache.size <= PREFLIGHT_CACHE_MAX_ENTRIES) break;
|
|
744
|
+
preflightCache.delete(cacheKey);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
function getPlaybookPreflightCacheTtlMs() {
|
|
748
|
+
return PREFLIGHT_CACHE_TTL_MS;
|
|
749
|
+
}
|
|
750
|
+
function getCachedPlaybookPreflight(scope) {
|
|
751
|
+
const cacheKey = buildKey(scope);
|
|
752
|
+
const entry = preflightCache.get(cacheKey);
|
|
753
|
+
if (!entry) return null;
|
|
754
|
+
if (entry.expiresAt <= Date.now() || entry.generation !== getPlaybookCacheGeneration(scope.key, scope.db)) {
|
|
755
|
+
preflightCache.delete(cacheKey);
|
|
756
|
+
return null;
|
|
757
|
+
}
|
|
758
|
+
return entry.report;
|
|
759
|
+
}
|
|
760
|
+
function setCachedPlaybookPreflight(scope, report, loadedAtGeneration) {
|
|
761
|
+
if (getPlaybookCacheGeneration(scope.key, scope.db) !== loadedAtGeneration) return;
|
|
762
|
+
preflightCache.set(buildKey(scope), {
|
|
763
|
+
expiresAt: Date.now() + PREFLIGHT_CACHE_TTL_MS,
|
|
764
|
+
generation: loadedAtGeneration,
|
|
765
|
+
report
|
|
766
|
+
});
|
|
767
|
+
if (preflightCache.size > PREFLIGHT_CACHE_MAX_ENTRIES) evict();
|
|
768
|
+
}
|
|
769
|
+
function clearPlaybookPreflightCache() {
|
|
770
|
+
preflightCache.clear();
|
|
771
|
+
}
|
|
772
|
+
//#endregion
|
|
773
|
+
//#region src/preflight.ts
|
|
774
|
+
var PLAYBOOK_PREFLIGHT_UNAVAILABLE = Object.freeze({
|
|
775
|
+
available: false,
|
|
776
|
+
advisory: true,
|
|
777
|
+
verdict: "deny",
|
|
778
|
+
steps: Object.freeze([]),
|
|
779
|
+
summary: Object.freeze({
|
|
780
|
+
allow: 0,
|
|
781
|
+
deny: 0,
|
|
782
|
+
unknown: 0
|
|
783
|
+
})
|
|
784
|
+
});
|
|
785
|
+
var VERDICT_RANK = {
|
|
786
|
+
allow: 0,
|
|
787
|
+
unknown: 1,
|
|
788
|
+
deny: 2
|
|
789
|
+
};
|
|
790
|
+
function worstVerdict(left, right) {
|
|
791
|
+
return VERDICT_RANK[right] > VERDICT_RANK[left] ? right : left;
|
|
792
|
+
}
|
|
793
|
+
function combineLayers(layers) {
|
|
794
|
+
let verdict = "allow";
|
|
795
|
+
for (const layer2 of layers) verdict = worstVerdict(verdict, layer2.verdict);
|
|
796
|
+
if (!layers.length) return {
|
|
797
|
+
verdict: "unknown",
|
|
798
|
+
reason: "not-evaluated"
|
|
799
|
+
};
|
|
800
|
+
const source = layers.find((layer2) => layer2.verdict === verdict);
|
|
801
|
+
return {
|
|
802
|
+
verdict,
|
|
803
|
+
reason: source?.reason ?? "ok"
|
|
804
|
+
};
|
|
805
|
+
}
|
|
806
|
+
function summarize(steps) {
|
|
807
|
+
const summary = {
|
|
808
|
+
allow: 0,
|
|
809
|
+
deny: 0,
|
|
810
|
+
unknown: 0
|
|
811
|
+
};
|
|
812
|
+
for (const step of steps) summary[step.verdict] += 1;
|
|
813
|
+
return summary;
|
|
814
|
+
}
|
|
815
|
+
async function preflightPlan(plan, evaluate) {
|
|
816
|
+
const steps = [];
|
|
817
|
+
for (const planStep of plan.steps) {
|
|
818
|
+
const { layers } = await evaluate(planStep);
|
|
819
|
+
steps.push(Object.freeze({
|
|
820
|
+
index: planStep.index,
|
|
821
|
+
kind: planStep.step.kind,
|
|
822
|
+
...combineLayers(layers),
|
|
823
|
+
layers: Object.freeze([...layers])
|
|
824
|
+
}));
|
|
825
|
+
}
|
|
826
|
+
let verdict = "allow";
|
|
827
|
+
for (const step of steps) verdict = worstVerdict(verdict, step.verdict);
|
|
828
|
+
return Object.freeze({
|
|
829
|
+
available: true,
|
|
830
|
+
advisory: true,
|
|
831
|
+
key: plan.key,
|
|
832
|
+
plane: plan.plane,
|
|
833
|
+
title: plan.title,
|
|
834
|
+
description: plan.description,
|
|
835
|
+
verdict,
|
|
836
|
+
steps: Object.freeze(steps),
|
|
837
|
+
summary: Object.freeze(summarize(steps))
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
async function equalizeUnknownKeyCost(key, options) {
|
|
841
|
+
if (!options?.db) return;
|
|
842
|
+
try {
|
|
843
|
+
const collection = await PlaybookOverrideCollection.create({ db: options.db });
|
|
844
|
+
const tenantId = options.tenantId !== void 0 ? options.tenantId : getTenantId() ?? null;
|
|
845
|
+
await collection.getResolutionLayers(key, tenantId);
|
|
846
|
+
} catch {}
|
|
847
|
+
}
|
|
848
|
+
async function normalizeCacheDb(db) {
|
|
849
|
+
if (!db) return db;
|
|
850
|
+
try {
|
|
851
|
+
return (await PlaybookOverrideCollection.create({ db })).db;
|
|
852
|
+
} catch {
|
|
853
|
+
return db;
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
async function preflightPlaybook(request) {
|
|
857
|
+
const { key, plane, principal, resolve, evaluate } = request;
|
|
858
|
+
const tenantId = resolve?.tenantId !== void 0 ? resolve.tenantId : getTenantId() ?? null;
|
|
859
|
+
const db = await normalizeCacheDb(resolve?.db);
|
|
860
|
+
const scope = {
|
|
861
|
+
principal,
|
|
862
|
+
key,
|
|
863
|
+
plane,
|
|
864
|
+
tenantId,
|
|
865
|
+
db
|
|
866
|
+
};
|
|
867
|
+
const cached = getCachedPlaybookPreflight(scope);
|
|
868
|
+
if (cached) return cached;
|
|
869
|
+
const loadedAtGeneration = getPlaybookCacheGeneration(key, db);
|
|
870
|
+
try {
|
|
871
|
+
const resolution = await resolvePlaybook(key, {
|
|
872
|
+
...resolve,
|
|
873
|
+
plane
|
|
874
|
+
});
|
|
875
|
+
if (!resolution.ok) {
|
|
876
|
+
if (resolution.reason === "unknown-playbook") await equalizeUnknownKeyCost(key, resolve);
|
|
877
|
+
setCachedPlaybookPreflight(scope, PLAYBOOK_PREFLIGHT_UNAVAILABLE, loadedAtGeneration);
|
|
878
|
+
return PLAYBOOK_PREFLIGHT_UNAVAILABLE;
|
|
879
|
+
}
|
|
880
|
+
const report = await preflightPlan(resolution.plan, evaluate);
|
|
881
|
+
setCachedPlaybookPreflight(scope, report, loadedAtGeneration);
|
|
882
|
+
return report;
|
|
883
|
+
} catch {
|
|
884
|
+
return PLAYBOOK_PREFLIGHT_UNAVAILABLE;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
function layer(layerName, verdict, reason, missingPermissions) {
|
|
888
|
+
return Object.freeze({
|
|
889
|
+
layer: layerName,
|
|
890
|
+
verdict,
|
|
891
|
+
reason,
|
|
892
|
+
...missingPermissions?.length ? { missingPermissions: Object.freeze([...missingPermissions]) } : {}
|
|
893
|
+
});
|
|
894
|
+
}
|
|
895
|
+
function createServerStepEvaluator(options) {
|
|
896
|
+
return async (planStep) => {
|
|
897
|
+
const step = planStep.step;
|
|
898
|
+
if (step.kind === "intent") return { layers: [(options.intentPlanes?.(step.id) ?? null)?.includes("server") ?? false ? layer("plane", "unknown", "intent-bridge-not-evaluated") : layer("plane", "deny", "plane")] };
|
|
899
|
+
const operation = step;
|
|
900
|
+
const toolLayer = options.isToolAllowed(operation) ? layer("tool-allowlist", "allow", "ok") : layer("tool-allowlist", "deny", "tool-not-allowed");
|
|
901
|
+
const permissionVerdict = await options.checkOperationPermission(operation);
|
|
902
|
+
return { layers: [toolLayer, permissionVerdict === "allow" ? layer("operation-permission", "allow", "ok") : permissionVerdict === "deny" ? layer("operation-permission", "deny", "permission-denied") : layer("operation-permission", "unknown", "permission-unknown")] };
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
function createBrowserStepEvaluator(options) {
|
|
906
|
+
const held = options.permissions ? new Set(options.permissions) : null;
|
|
907
|
+
return (planStep) => {
|
|
908
|
+
const step = planStep.step;
|
|
909
|
+
if (step.kind === "intent") return { layers: [layer("intent-mount", "unknown", "intent-not-mounted")] };
|
|
910
|
+
const { model, action } = step;
|
|
911
|
+
const layers = [];
|
|
912
|
+
const exposed = options.layers.isActionExposed(model, action);
|
|
913
|
+
layers.push(exposed ? layer("action-exposure", "allow", "ok") : layer("action-exposure", "deny", "action-not-exposed"));
|
|
914
|
+
const isPublic = options.layers.isRoutePublic(model, action);
|
|
915
|
+
const appAuthConfigured = options.layers.appAuthConfigured;
|
|
916
|
+
layers.push(isPublic ? layer("public-access", "allow", "ok") : appAuthConfigured ? layer("public-access", "unknown", "auth-required") : layer("public-access", "deny", "not-public"));
|
|
917
|
+
const required = options.layers.requiredFieldPermissions(model, action);
|
|
918
|
+
if (!required.length) layers.push(layer("field-permissions", "allow", "ok"));
|
|
919
|
+
else if (!held) layers.push(layer("field-permissions", "unknown", "field-permissions-unknown"));
|
|
920
|
+
else {
|
|
921
|
+
const missing = required.filter((slug) => !held.has(slug));
|
|
922
|
+
layers.push(missing.length ? layer("field-permissions", "allow", "fields-redacted", missing) : layer("field-permissions", "allow", "ok"));
|
|
923
|
+
}
|
|
924
|
+
layers.push(appAuthConfigured ? layer("app-auth", "unknown", "app-auth-not-evaluated") : layer("app-auth", "allow", "app-auth-not-configured"));
|
|
925
|
+
return { layers };
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
//#endregion
|
|
929
|
+
//#region src/rest-preflight.ts
|
|
930
|
+
function createRestPreflightLayerSource(options) {
|
|
931
|
+
return {
|
|
932
|
+
appAuthConfigured: options.appAuthConfigured,
|
|
933
|
+
isActionExposed(model, action) {
|
|
934
|
+
const objectName = resolveRegisteredObjectName(model);
|
|
935
|
+
if (!objectName) return false;
|
|
936
|
+
return isRestActionRoutable(objectName, action) && isApiActionEnabledForObject(objectName, action);
|
|
937
|
+
},
|
|
938
|
+
isRoutePublic(model, action) {
|
|
939
|
+
const objectName = resolveRegisteredObjectName(model);
|
|
940
|
+
if (!objectName) return false;
|
|
941
|
+
return isRestRoutePublic(objectName, restMethodForApiAction(action, objectName));
|
|
942
|
+
},
|
|
943
|
+
requiredFieldPermissions(model) {
|
|
944
|
+
const objectName = resolveRegisteredObjectName(model);
|
|
945
|
+
if (!objectName) return [];
|
|
946
|
+
return restFieldReadPermissions(objectName);
|
|
947
|
+
}
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
function defaultPrincipal(request) {
|
|
951
|
+
return `${request.permissions ? `perm:${[...request.permissions].sort().join(",")}` : "perm:unpublished"}|auth:${request.appAuthConfigured ? "wired" : "none"}`;
|
|
952
|
+
}
|
|
953
|
+
function createBrowserPlaybookPreflight(options = {}) {
|
|
954
|
+
return async (request) => {
|
|
955
|
+
const layers = createRestPreflightLayerSource({ appAuthConfigured: request.appAuthConfigured });
|
|
956
|
+
return preflightPlaybook({
|
|
957
|
+
key: request.key,
|
|
958
|
+
plane: "browser",
|
|
959
|
+
principal: (options.principal ?? defaultPrincipal)(request),
|
|
960
|
+
resolve: {
|
|
961
|
+
...options.resolve,
|
|
962
|
+
...request.db === void 0 ? {} : { db: request.db }
|
|
963
|
+
},
|
|
964
|
+
evaluate: createBrowserStepEvaluator({
|
|
965
|
+
layers,
|
|
966
|
+
permissions: request.permissions ?? null
|
|
967
|
+
})
|
|
968
|
+
});
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
//#endregion
|
|
729
972
|
//#region src/index.ts
|
|
730
973
|
var PACKAGE_VERSION_INITIALIZED = true;
|
|
731
974
|
//#endregion
|
|
732
|
-
export { FAIL_CLOSED_CLASSIFICATION, PACKAGE_VERSION_INITIALIZED, PLAYBOOK_PLANES, PlaybookOverride, PlaybookOverrideCollection, PlaybookRegistry, clearPlaybookCache, definePlaybook, getPlaybookCacheTtlMs, normalizeEditableConfig, resolvePlaybook };
|
|
975
|
+
export { FAIL_CLOSED_CLASSIFICATION, PACKAGE_VERSION_INITIALIZED, PLAYBOOK_PLANES, PLAYBOOK_PREFLIGHT_UNAVAILABLE, PlaybookOverride, PlaybookOverrideCollection, PlaybookRegistry, clearPlaybookCache, clearPlaybookPreflightCache, createBrowserPlaybookPreflight, createBrowserStepEvaluator, createRestPreflightLayerSource, createServerStepEvaluator, definePlaybook, getPlaybookCacheTtlMs, getPlaybookPreflightCacheTtlMs, normalizeEditableConfig, preflightPlan, preflightPlaybook, resolvePlaybook, worstVerdict };
|
|
733
976
|
|
|
734
977
|
//# sourceMappingURL=index.js.map
|