@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/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.44.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\"]}"));
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