diff --git a/policy-site/src/ui/policy-document.ts b/policy-site/src/ui/policy-document.ts index 7e310d64..d31373a6 100644 --- a/policy-site/src/ui/policy-document.ts +++ b/policy-site/src/ui/policy-document.ts @@ -90,6 +90,17 @@ export function joinDocument( return { value: ordered(isObject(loaded) ? loaded : {}, fields) }; } +/** + * The engine a new policy starts in, where this build has it: Cedar, whose + * documents are text rather than JSON. + */ +export const NEW_POLICY_ENGINE = "bot.did.policy#cedar"; + +/** The engine a new policy starts in, out of the ones this build carries. */ +export function defaultEngine(engines: string[]): string | undefined { + return engines.includes(NEW_POLICY_ENGINE) ? NEW_POLICY_ENGINE : engines[0]; +} + /** An empty document of `type`, as editor text. */ export function emptyDocument(type: string): DocumentText { const engine = DOCUMENT_BODIES[type]; diff --git a/policy-site/src/ui/policy-editor.ts b/policy-site/src/ui/policy-editor.ts index bea40857..eea4734c 100644 --- a/policy-site/src/ui/policy-editor.ts +++ b/policy-site/src/ui/policy-editor.ts @@ -10,6 +10,7 @@ import { checkboxes, debounce, labelled, renderReport, stamp, type EditorTarget import { actionsOf, assemblePolicy, + defaultEngine, emptyDocument, joinDocument, languageOf, @@ -50,8 +51,8 @@ export function policyEditor(checks: Checks, target: EditorTarget): PolicyEditor const createdAt = h("input", { attrs: { readonly: "" } }); createdAt.value = typeof loaded.createdAt === "string" ? loaded.createdAt : ""; - // A new policy with no document starts as the first engine's, empty. - const first = vocabulary.engines[0]; + // A new policy with no document starts empty, in the default engine. + const first = defaultEngine(vocabulary.engines); let held: DocumentText = loaded.document === undefined && first ? emptyDocument(first) : start.document; const modeOf = (doc: DocumentText): EditorMode => diff --git a/policy-site/tests/check-flows.mjs b/policy-site/tests/check-flows.mjs index 6e8f678e..ce50455f 100644 --- a/policy-site/tests/check-flows.mjs +++ b/policy-site/tests/check-flows.mjs @@ -216,6 +216,16 @@ function expectWrites(name, batch, writes) { } } +// A new policy starts in the engine whose documents are Cedar text. +{ + const { defaultEngine, emptyDocument } = await import("../src/ui/policy-document.ts"); + const engines = ["bot.did.policy#regex", "bot.did.policy#cedar"]; + if (defaultEngine(engines) !== "bot.did.policy#cedar") fail(`a new policy starts as ${defaultEngine(engines)}`); + const started = emptyDocument(defaultEngine(engines)); + if (started.text !== "" || started.whole) fail(`a new Cedar policy starts as ${JSON.stringify(started)}`); + if (defaultEngine(["bot.did.policy#regex"]) !== "bot.did.policy#regex") fail("a build without Cedar does not fall back"); +} + // A sign-in comes back only to one of the page's own addresses. { const back = "/recommended/no-posts/customize/edit";