@overaihq/cli 0.14.6 → 0.14.7
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 +136 -115
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -35733,6 +35733,7 @@ var ID_PREFIXES = {
|
|
|
35733
35733
|
automation_email_address: { prefix: "aea", body: 10 },
|
|
35734
35734
|
automation_email_alert: { prefix: "aes", body: 10 },
|
|
35735
35735
|
automation_error_alert_queue: { prefix: "aeaq", body: 10 },
|
|
35736
|
+
billing_period: { prefix: "bpd", body: 12 },
|
|
35736
35737
|
browser_automation: { prefix: "bra", body: 10 },
|
|
35737
35738
|
browser_automation_run: { prefix: "brr", body: 20 },
|
|
35738
35739
|
browser_session_usage: { prefix: "bsu", body: 12 },
|
|
@@ -35837,6 +35838,108 @@ var idTableByPrefix = (id) => {
|
|
|
35837
35838
|
return best?.table ?? null;
|
|
35838
35839
|
};
|
|
35839
35840
|
|
|
35841
|
+
// src/commands/resource.ts
|
|
35842
|
+
var resources = {
|
|
35843
|
+
workspace: { collection: "workspaces", mutation: "updateWorkspace", result: "workspace", patch: "WorkspacePatch", fields: "id name description isArchived", editable: ["name", "description", "isArchived"] },
|
|
35844
|
+
automation: { collection: "automations", mutation: "updateAutomation", result: "automation", patch: "AutomationPatch", fields: "id name description isArchived isActive workspaceId", editable: ["name", "description", "isArchived", "isActive"] },
|
|
35845
|
+
function: { collection: "functions", mutation: "updateFunction", result: "function", patch: "FunctionPatch", fields: "id name description isArchived isEnabled workspaceId", editable: ["name", "description", "isArchived", "isEnabled"] },
|
|
35846
|
+
web_page: { collection: "webPages", mutation: "updateWebPage", result: "webPage", patch: "WebPagePatch", fields: "id name isArchived workspaceId", editable: ["name", "isArchived"] },
|
|
35847
|
+
printable_page: { collection: "printablePages", mutation: "updatePrintablePage", result: "printablePage", patch: "PrintablePagePatch", fields: "id name isArchived workspaceId", editable: ["name", "isArchived"] },
|
|
35848
|
+
agent: { collection: "agents", mutation: "updateAgent", result: "agent", patch: "AgentPatch", fields: "id name description isArchived isEnabled workspaceId", editable: ["name", "description", "isArchived", "isEnabled"] },
|
|
35849
|
+
integration: { collection: "integrations", mutation: "updateIntegration", result: "integration", patch: "IntegrationPatch", fields: "id name description isArchived integrationTypeId workspaceId", editable: ["name", "description", "isArchived", "integrationTypeId"] },
|
|
35850
|
+
table_space: { collection: "tableSpaces", mutation: "updateTableSpace", result: "tableSpace", patch: "TableSpacePatch", fields: "id name description isArchived workspaceId", editable: ["name", "description", "isArchived"] },
|
|
35851
|
+
data_stream: { collection: "dataStreams", mutation: "updateDataStream", result: "dataStream", patch: "DataStreamPatch", fields: "id name description isArchived workspaceId", editable: ["name", "description", "isArchived"] },
|
|
35852
|
+
knowledge_base: { collection: "knowledgeBases", mutation: "updateKnowledgeBase", result: "knowledgeBase", patch: "KnowledgeBasePatch", fields: "id name description isArchived embeddingModel workspaceId", editable: ["name", "description", "isArchived"] },
|
|
35853
|
+
data_file: { collection: "dataFiles", mutation: "updateDataFile", result: "dataFile", patch: "DataFilePatch", fields: "id name description isArchived workspaceId", editable: ["name", "description", "isArchived"] },
|
|
35854
|
+
action_runner: { collection: "actionRunners", mutation: "updateActionRunner", result: "actionRunner", patch: "ActionRunnerPatch", fields: "id isArchived actionTimeoutSeconds config workspaceId identityId identity { name }", editable: ["isArchived", "actionTimeoutSeconds", "config"] }
|
|
35855
|
+
// Keyed by table so `idTableByPrefix` can index it; `satisfies` rejects a key
|
|
35856
|
+
// the registry does not know.
|
|
35857
|
+
};
|
|
35858
|
+
var resourceFor = (id) => {
|
|
35859
|
+
const table = idTableByPrefix(id);
|
|
35860
|
+
const resource = table == null ? void 0 : resources[table];
|
|
35861
|
+
if (resource == null) throw new Error(`Unsupported resource id: ${id}`);
|
|
35862
|
+
return resource;
|
|
35863
|
+
};
|
|
35864
|
+
var readResource = async (id, resource) => {
|
|
35865
|
+
const data = await gqlRequest(
|
|
35866
|
+
`query CliResource($id: String!) {
|
|
35867
|
+
${resource.collection}(condition: { idIgnoringCase: $id }, includeArchived: YES, first: 1) {
|
|
35868
|
+
nodes { ${resource.fields} }
|
|
35869
|
+
}
|
|
35870
|
+
}`,
|
|
35871
|
+
{ id }
|
|
35872
|
+
);
|
|
35873
|
+
const row = data[resource.collection]?.nodes[0];
|
|
35874
|
+
if (row == null) throw new Error(`Resource ${id} not found.`);
|
|
35875
|
+
return row;
|
|
35876
|
+
};
|
|
35877
|
+
var runResource = async (args) => {
|
|
35878
|
+
const [operation, id] = args;
|
|
35879
|
+
if (operation !== "show" && operation !== "update" || id == null) {
|
|
35880
|
+
throw new Error("Usage: overai resource show <id> | resource update <id> [--name <name>] [--description <text>] [--archive|--restore] [--enable|--disable] [--active|--inactive]");
|
|
35881
|
+
}
|
|
35882
|
+
const resource = resourceFor(id);
|
|
35883
|
+
if (operation === "show") {
|
|
35884
|
+
printResult(await readResource(id, resource), resolveFormat(flagValue(args, "-o", "--output")));
|
|
35885
|
+
return;
|
|
35886
|
+
}
|
|
35887
|
+
const patch = {};
|
|
35888
|
+
const scalarFlags = [
|
|
35889
|
+
["name", "--name"],
|
|
35890
|
+
["description", "--description"],
|
|
35891
|
+
["integrationTypeId", "--type"],
|
|
35892
|
+
["actionTimeoutSeconds", "--timeout"]
|
|
35893
|
+
];
|
|
35894
|
+
scalarFlags.forEach(([field, flag]) => {
|
|
35895
|
+
const value = flagValue(args, flag);
|
|
35896
|
+
if (value != null && resource.editable.includes(field)) {
|
|
35897
|
+
patch[field] = field === "actionTimeoutSeconds" ? Number(value) : value;
|
|
35898
|
+
}
|
|
35899
|
+
});
|
|
35900
|
+
[
|
|
35901
|
+
["isArchived", "--archive", true],
|
|
35902
|
+
["isArchived", "--restore", false],
|
|
35903
|
+
["isEnabled", "--enable", true],
|
|
35904
|
+
["isEnabled", "--disable", false],
|
|
35905
|
+
["isActive", "--active", true],
|
|
35906
|
+
["isActive", "--inactive", false]
|
|
35907
|
+
].forEach(([field, flag, value]) => {
|
|
35908
|
+
if (args.includes(flag) && resource.editable.includes(field)) patch[field] = value;
|
|
35909
|
+
});
|
|
35910
|
+
const config = await readValue(flagValue(args, "--config"), "--config");
|
|
35911
|
+
if (config != null && resource.editable.includes("config")) {
|
|
35912
|
+
try {
|
|
35913
|
+
patch.config = JSON.parse(config);
|
|
35914
|
+
} catch {
|
|
35915
|
+
throw new Error("--config must be valid JSON (or @<file> containing JSON).");
|
|
35916
|
+
}
|
|
35917
|
+
}
|
|
35918
|
+
const current = await readResource(id, resource);
|
|
35919
|
+
const name2 = flagValue(args, "--name");
|
|
35920
|
+
if (name2 != null && idTableByPrefix(id) === "action_runner") {
|
|
35921
|
+
const result = await gqlRequest(
|
|
35922
|
+
`mutation CliRenameRunner($id: String!, $name: String!) {
|
|
35923
|
+
updateIdentity(input: { id: $id, patch: { name: $name } }) { identity { id } }
|
|
35924
|
+
}`,
|
|
35925
|
+
{ id: current.identityId, name: name2 }
|
|
35926
|
+
);
|
|
35927
|
+
if (result.updateIdentity?.identity == null) throw new Error(`Runner ${id} could not be renamed; check your workspace role.`);
|
|
35928
|
+
}
|
|
35929
|
+
if (Object.keys(patch).length > 0) {
|
|
35930
|
+
const result = await gqlRequest(
|
|
35931
|
+
`mutation CliUpdateResource($id: String!, $patch: ${resource.patch}!) {
|
|
35932
|
+
${resource.mutation}(input: { id: $id, patch: $patch }) { updated: ${resource.result} { id } }
|
|
35933
|
+
}`,
|
|
35934
|
+
{ id: current.id, patch }
|
|
35935
|
+
);
|
|
35936
|
+
if (result[resource.mutation]?.updated == null) throw new Error(`Resource ${id} was not updated; check that it exists and your workspace role allows editing.`);
|
|
35937
|
+
} else if (!(name2 != null && idTableByPrefix(id) === "action_runner")) {
|
|
35938
|
+
throw new Error(`No supported changes supplied for ${id}.`);
|
|
35939
|
+
}
|
|
35940
|
+
printResult(await readResource(current.id, resource), resolveFormat(flagValue(args, "-o", "--output")));
|
|
35941
|
+
};
|
|
35942
|
+
|
|
35840
35943
|
// src/commands/open.ts
|
|
35841
35944
|
var ROUTE_BY_TYPE = {
|
|
35842
35945
|
automation: "automations",
|
|
@@ -35862,7 +35965,7 @@ var ROUTE_BY_TABLE = {
|
|
|
35862
35965
|
var runOpen = async (args) => {
|
|
35863
35966
|
const filter2 = args.find((a) => !a.startsWith("-"));
|
|
35864
35967
|
const { organizationId } = await getAccessToken();
|
|
35865
|
-
const url = (() => {
|
|
35968
|
+
const url = await (async () => {
|
|
35866
35969
|
const manifest = (() => {
|
|
35867
35970
|
try {
|
|
35868
35971
|
return readManifest(findWorkspaceRoot());
|
|
@@ -35875,11 +35978,11 @@ var runOpen = async (args) => {
|
|
|
35875
35978
|
return `${appBaseUrl(apiBaseUrl())}/${manifest.organizationId}/workspaces/${manifest.workspaceId}`;
|
|
35876
35979
|
}
|
|
35877
35980
|
const match = Object.entries(manifest.resources).find(
|
|
35878
|
-
([
|
|
35981
|
+
([id2, r]) => id2.toLowerCase() === filter2.toLowerCase() || r.name.toLowerCase().includes(filter2.toLowerCase()) || r.files.some((f) => f.includes(filter2))
|
|
35879
35982
|
);
|
|
35880
35983
|
if (match != null) {
|
|
35881
|
-
const [
|
|
35882
|
-
return `${appBaseUrl(apiBaseUrl())}/${manifest.organizationId}/${ROUTE_BY_TYPE[
|
|
35984
|
+
const [id2, resource2] = match;
|
|
35985
|
+
return `${appBaseUrl(apiBaseUrl())}/${manifest.organizationId}/${ROUTE_BY_TYPE[resource2.type]}/${id2}`;
|
|
35883
35986
|
}
|
|
35884
35987
|
}
|
|
35885
35988
|
if (filter2 == null) {
|
|
@@ -35894,7 +35997,9 @@ var runOpen = async (args) => {
|
|
|
35894
35997
|
`Nothing matched "${filter2}" (not a tracked resource or a recognized id prefix).`
|
|
35895
35998
|
);
|
|
35896
35999
|
}
|
|
35897
|
-
|
|
36000
|
+
const resource = table == null ? void 0 : resources[table];
|
|
36001
|
+
const id = resource == null ? filter2 : (await readResource(filter2, resource)).id;
|
|
36002
|
+
return `${appBaseUrl(apiBaseUrl())}/${organizationId}/${route}/${id}`;
|
|
35898
36003
|
})();
|
|
35899
36004
|
process.stdout.write(`${url}
|
|
35900
36005
|
`);
|
|
@@ -36839,108 +36944,6 @@ var runReport = async (args) => {
|
|
|
36839
36944
|
);
|
|
36840
36945
|
};
|
|
36841
36946
|
|
|
36842
|
-
// src/commands/resource.ts
|
|
36843
|
-
var resources = {
|
|
36844
|
-
workspace: { collection: "workspaces", mutation: "updateWorkspace", result: "workspace", patch: "WorkspacePatch", fields: "id name description isArchived", editable: ["name", "description", "isArchived"] },
|
|
36845
|
-
automation: { collection: "automations", mutation: "updateAutomation", result: "automation", patch: "AutomationPatch", fields: "id name description isArchived isActive workspaceId", editable: ["name", "description", "isArchived", "isActive"] },
|
|
36846
|
-
function: { collection: "functions", mutation: "updateFunction", result: "function", patch: "FunctionPatch", fields: "id name description isArchived isEnabled workspaceId", editable: ["name", "description", "isArchived", "isEnabled"] },
|
|
36847
|
-
web_page: { collection: "webPages", mutation: "updateWebPage", result: "webPage", patch: "WebPagePatch", fields: "id name isArchived workspaceId", editable: ["name", "isArchived"] },
|
|
36848
|
-
printable_page: { collection: "printablePages", mutation: "updatePrintablePage", result: "printablePage", patch: "PrintablePagePatch", fields: "id name isArchived workspaceId", editable: ["name", "isArchived"] },
|
|
36849
|
-
agent: { collection: "agents", mutation: "updateAgent", result: "agent", patch: "AgentPatch", fields: "id name description isArchived isEnabled workspaceId", editable: ["name", "description", "isArchived", "isEnabled"] },
|
|
36850
|
-
integration: { collection: "integrations", mutation: "updateIntegration", result: "integration", patch: "IntegrationPatch", fields: "id name description isArchived integrationTypeId workspaceId", editable: ["name", "description", "isArchived", "integrationTypeId"] },
|
|
36851
|
-
table_space: { collection: "tableSpaces", mutation: "updateTableSpace", result: "tableSpace", patch: "TableSpacePatch", fields: "id name description isArchived workspaceId", editable: ["name", "description", "isArchived"] },
|
|
36852
|
-
data_stream: { collection: "dataStreams", mutation: "updateDataStream", result: "dataStream", patch: "DataStreamPatch", fields: "id name description isArchived workspaceId", editable: ["name", "description", "isArchived"] },
|
|
36853
|
-
knowledge_base: { collection: "knowledgeBases", mutation: "updateKnowledgeBase", result: "knowledgeBase", patch: "KnowledgeBasePatch", fields: "id name description isArchived embeddingModel workspaceId", editable: ["name", "description", "isArchived"] },
|
|
36854
|
-
data_file: { collection: "dataFiles", mutation: "updateDataFile", result: "dataFile", patch: "DataFilePatch", fields: "id name description isArchived workspaceId", editable: ["name", "description", "isArchived"] },
|
|
36855
|
-
action_runner: { collection: "actionRunners", mutation: "updateActionRunner", result: "actionRunner", patch: "ActionRunnerPatch", fields: "id isArchived actionTimeoutSeconds config workspaceId identityId identity { name }", editable: ["isArchived", "actionTimeoutSeconds", "config"] }
|
|
36856
|
-
// Keyed by table so `idTableByPrefix` can index it; `satisfies` rejects a key
|
|
36857
|
-
// the registry does not know.
|
|
36858
|
-
};
|
|
36859
|
-
var resourceFor = (id) => {
|
|
36860
|
-
const table = idTableByPrefix(id);
|
|
36861
|
-
const resource = table == null ? void 0 : resources[table];
|
|
36862
|
-
if (resource == null) throw new Error(`Unsupported resource id: ${id}`);
|
|
36863
|
-
return resource;
|
|
36864
|
-
};
|
|
36865
|
-
var readResource = async (id, resource) => {
|
|
36866
|
-
const data = await gqlRequest(
|
|
36867
|
-
`query CliResource($id: String!) {
|
|
36868
|
-
${resource.collection}(condition: { id: $id }, includeArchived: YES, first: 1) {
|
|
36869
|
-
nodes { ${resource.fields} }
|
|
36870
|
-
}
|
|
36871
|
-
}`,
|
|
36872
|
-
{ id }
|
|
36873
|
-
);
|
|
36874
|
-
const row = data[resource.collection]?.nodes[0];
|
|
36875
|
-
if (row == null) throw new Error(`Resource ${id} not found.`);
|
|
36876
|
-
return row;
|
|
36877
|
-
};
|
|
36878
|
-
var runResource = async (args) => {
|
|
36879
|
-
const [operation, id] = args;
|
|
36880
|
-
if (operation !== "show" && operation !== "update" || id == null) {
|
|
36881
|
-
throw new Error("Usage: overai resource show <id> | resource update <id> [--name <name>] [--description <text>] [--archive|--restore] [--enable|--disable] [--active|--inactive]");
|
|
36882
|
-
}
|
|
36883
|
-
const resource = resourceFor(id);
|
|
36884
|
-
if (operation === "show") {
|
|
36885
|
-
printResult(await readResource(id, resource), resolveFormat(flagValue(args, "-o", "--output")));
|
|
36886
|
-
return;
|
|
36887
|
-
}
|
|
36888
|
-
const patch = {};
|
|
36889
|
-
const scalarFlags = [
|
|
36890
|
-
["name", "--name"],
|
|
36891
|
-
["description", "--description"],
|
|
36892
|
-
["integrationTypeId", "--type"],
|
|
36893
|
-
["actionTimeoutSeconds", "--timeout"]
|
|
36894
|
-
];
|
|
36895
|
-
scalarFlags.forEach(([field, flag]) => {
|
|
36896
|
-
const value = flagValue(args, flag);
|
|
36897
|
-
if (value != null && resource.editable.includes(field)) {
|
|
36898
|
-
patch[field] = field === "actionTimeoutSeconds" ? Number(value) : value;
|
|
36899
|
-
}
|
|
36900
|
-
});
|
|
36901
|
-
[
|
|
36902
|
-
["isArchived", "--archive", true],
|
|
36903
|
-
["isArchived", "--restore", false],
|
|
36904
|
-
["isEnabled", "--enable", true],
|
|
36905
|
-
["isEnabled", "--disable", false],
|
|
36906
|
-
["isActive", "--active", true],
|
|
36907
|
-
["isActive", "--inactive", false]
|
|
36908
|
-
].forEach(([field, flag, value]) => {
|
|
36909
|
-
if (args.includes(flag) && resource.editable.includes(field)) patch[field] = value;
|
|
36910
|
-
});
|
|
36911
|
-
const config = await readValue(flagValue(args, "--config"), "--config");
|
|
36912
|
-
if (config != null && resource.editable.includes("config")) {
|
|
36913
|
-
try {
|
|
36914
|
-
patch.config = JSON.parse(config);
|
|
36915
|
-
} catch {
|
|
36916
|
-
throw new Error("--config must be valid JSON (or @<file> containing JSON).");
|
|
36917
|
-
}
|
|
36918
|
-
}
|
|
36919
|
-
const name2 = flagValue(args, "--name");
|
|
36920
|
-
if (name2 != null && idTableByPrefix(id) === "action_runner") {
|
|
36921
|
-
const current = await readResource(id, resource);
|
|
36922
|
-
const result = await gqlRequest(
|
|
36923
|
-
`mutation CliRenameRunner($id: String!, $name: String!) {
|
|
36924
|
-
updateIdentity(input: { id: $id, patch: { name: $name } }) { identity { id } }
|
|
36925
|
-
}`,
|
|
36926
|
-
{ id: current.identityId, name: name2 }
|
|
36927
|
-
);
|
|
36928
|
-
if (result.updateIdentity?.identity == null) throw new Error(`Runner ${id} could not be renamed; check your workspace role.`);
|
|
36929
|
-
}
|
|
36930
|
-
if (Object.keys(patch).length > 0) {
|
|
36931
|
-
const result = await gqlRequest(
|
|
36932
|
-
`mutation CliUpdateResource($id: String!, $patch: ${resource.patch}!) {
|
|
36933
|
-
${resource.mutation}(input: { id: $id, patch: $patch }) { updated: ${resource.result} { id } }
|
|
36934
|
-
}`,
|
|
36935
|
-
{ id, patch }
|
|
36936
|
-
);
|
|
36937
|
-
if (result[resource.mutation]?.updated == null) throw new Error(`Resource ${id} was not updated; check that it exists and your workspace role allows editing.`);
|
|
36938
|
-
} else if (!(name2 != null && idTableByPrefix(id) === "action_runner")) {
|
|
36939
|
-
throw new Error(`No supported changes supplied for ${id}.`);
|
|
36940
|
-
}
|
|
36941
|
-
printResult(await readResource(id, resource), resolveFormat(flagValue(args, "-o", "--output")));
|
|
36942
|
-
};
|
|
36943
|
-
|
|
36944
36947
|
// src/docs/bestPractices.ts
|
|
36945
36948
|
var platform2 = `# OverAI platform primer
|
|
36946
36949
|
|
|
@@ -37056,7 +37059,20 @@ A page version's config JSON carries the code; the CLI splits it into
|
|
|
37056
37059
|
language, customTitle, hideTopBar, ...). Push reassembles them.
|
|
37057
37060
|
|
|
37058
37061
|
- Web pages are React (TSX). Printable pages are React or Liquid.
|
|
37059
|
-
- Web page config authorizationMode defaults to "workspace"
|
|
37062
|
+
- Web page config authorizationMode defaults to "workspace": every end user
|
|
37063
|
+
who opens the page gets a workspace token that can read AND write every
|
|
37064
|
+
table space in the workspace and any shared into it, call any function it
|
|
37065
|
+
reaches, trigger any of its automations, and call any agent visible to it.
|
|
37066
|
+
Four rules follow:
|
|
37067
|
+
1. The workspace is the unit of trust. Everything in it trusts everything
|
|
37068
|
+
else, and a page's end users count as "in it."
|
|
37069
|
+
2. A public workspace is public all the way down. Public (or
|
|
37070
|
+
password-protected) is a workspace setting, not a page setting; every table space, function, automation
|
|
37071
|
+
and agent in it is reachable by anyone who can open a page.
|
|
37072
|
+
3. Sharing into a workspace extends its trust. A table space shared into a
|
|
37073
|
+
public or password-protected workspace is public.
|
|
37074
|
+
4. Cross a trust line with a function, not a table. Keep data in a private
|
|
37075
|
+
workspace and share a function into the page's workspace.
|
|
37060
37076
|
Opt into "viewer" for personal pages spanning the signed-in viewer's workspaces.
|
|
37061
37077
|
Page code uses their permissions; results/access errors can differ by user.
|
|
37062
37078
|
Public links require sign-in. Save and deploy publishes the mode with the code.
|
|
@@ -37102,8 +37118,9 @@ language, customTitle, hideTopBar, ...). Push reassembles them.
|
|
|
37102
37118
|
null. Identity-scoped features degrade: useAgentChat streams but persists
|
|
37103
37119
|
nothing (conversationId stays null, useAgentConversations is empty, the
|
|
37104
37120
|
conversation helpers throw), and author-requiring writes like
|
|
37105
|
-
env.DFxxx.saveVersion 401.
|
|
37106
|
-
|
|
37121
|
+
env.DFxxx.saveVersion 401. The page runs on the workspace token, so anyone
|
|
37122
|
+
with the link can read and write every table space and call every function,
|
|
37123
|
+
automation and agent the workspace reaches (rule 2 above).
|
|
37107
37124
|
- meta.json \`runtime\`: "v2" serves the page from its own origin (separate
|
|
37108
37125
|
process, real localStorage/cookies \u2014 no noSandbox needed); absent or "v1" is
|
|
37109
37126
|
the sandboxed srcdoc iframe. Anything else is rejected on push.
|
|
@@ -37149,11 +37166,15 @@ esm.sh imports allowed. The CLI materializes <slug>.<id>.ts (code) and
|
|
|
37149
37166
|
executionMemory MB, callerAccess).
|
|
37150
37167
|
|
|
37151
37168
|
- New functions allow only callers with workspace access by default. Set
|
|
37152
|
-
callerAccess to "
|
|
37153
|
-
|
|
37154
|
-
|
|
37155
|
-
|
|
37156
|
-
|
|
37169
|
+
callerAccess to "organization" to accept members of the function's organization
|
|
37170
|
+
or tokens from any private workspace in that organization without a share.
|
|
37171
|
+
A public-workspace token does not qualify; when a token has both workspace and
|
|
37172
|
+
user claims, the workspace claim takes precedence. Set callerAccess to "public"
|
|
37173
|
+
only when an unauthenticated endpoint is intended. Existing functions retain
|
|
37174
|
+
their saved policy when older meta.json files omit this field. The policy is
|
|
37175
|
+
versioned: deploy the saved version to change live access. Use Authorization
|
|
37176
|
+
for the platform bearer token; put application credentials in another header.
|
|
37177
|
+
Test as a user, a workspace, and anonymous before deploying.
|
|
37157
37178
|
- Functions are full HTTP apps: method + sub-path are forwarded to your code,
|
|
37158
37179
|
and each execution records requestMethod/requestPath. Callers reach a route
|
|
37159
37180
|
with env.FNxxx.call({ method, path: "/features/123" }) \u2014 path defaults to the
|