@tailor-platform/sdk 1.80.1 → 1.82.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.
Files changed (70) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/application-CP0W2sQo.mjs +3 -0
  3. package/dist/{application-C1d52JP9.mjs → application-CVeA53ok.mjs} +172 -27
  4. package/dist/application-CVeA53ok.mjs.map +1 -0
  5. package/dist/cli/index.mjs +19 -34
  6. package/dist/cli/index.mjs.map +1 -1
  7. package/dist/cli/lib.mjs +2 -2
  8. package/dist/cli/skills.mjs +1 -1
  9. package/dist/completion/zsh-worker.zsh +1 -1
  10. package/dist/configure/config/types.d.mts +3 -1
  11. package/dist/configure/index.d.mts +2 -1
  12. package/dist/configure/index.mjs +9 -0
  13. package/dist/configure/index.mjs.map +1 -1
  14. package/dist/configure/services/idp/permission.d.mts +1 -16
  15. package/dist/configure/services/index.d.mts +2 -1
  16. package/dist/configure/services/resolver/index.d.mts +2 -1
  17. package/dist/configure/services/resolver/permission.d.mts +64 -0
  18. package/dist/configure/services/resolver/resolver.d.mts +14 -2
  19. package/dist/configure/services/tailordb/permission.d.mts +1 -16
  20. package/dist/configure/types/permission-operand.types.d.mts +20 -0
  21. package/dist/{crashreport-BNWUM6Kf.mjs → crashreport-DMYuHnBN.mjs} +2 -2
  22. package/dist/{crashreport-BNWUM6Kf.mjs.map → crashreport-DMYuHnBN.mjs.map} +1 -1
  23. package/dist/{crashreport-BafWvjjX.mjs → crashreport-ecqnz51B.mjs} +1 -1
  24. package/dist/{globals-DVJ8RVvm.mjs → globals-DUqEetIh.mjs} +11 -2
  25. package/dist/{globals-DVJ8RVvm.mjs.map → globals-DUqEetIh.mjs.map} +1 -1
  26. package/dist/{logger-BwS4ppwO.mjs → logger-CXQq9YIp.mjs} +110 -13
  27. package/dist/logger-CXQq9YIp.mjs.map +1 -0
  28. package/dist/logger-t5ASCDZm.mjs +49 -0
  29. package/dist/logger-t5ASCDZm.mjs.map +1 -0
  30. package/dist/{register-typescript-runtime-Bd4bcLbW.mjs → register-typescript-runtime-O7zQNif0.mjs} +44 -17
  31. package/dist/register-typescript-runtime-O7zQNif0.mjs.map +1 -0
  32. package/dist/runtime/globals.d.mts +7 -0
  33. package/dist/runtime/index.d.mts +3 -1
  34. package/dist/runtime/index.mjs +2 -1
  35. package/dist/runtime/logger.d.mts +98 -0
  36. package/dist/runtime/logger.mjs +3 -0
  37. package/dist/{service-CDPatibu.mjs → service-B0MaodSg.mjs} +2 -2
  38. package/dist/{service-CDPatibu.mjs.map → service-B0MaodSg.mjs.map} +1 -1
  39. package/dist/{service-Cp0I7ZFe.mjs → service-CIGSGg9I.mjs} +2 -2
  40. package/dist/{service-Cp0I7ZFe.mjs.map → service-CIGSGg9I.mjs.map} +1 -1
  41. package/dist/service-KnAiVofD.mjs +3 -0
  42. package/dist/{service_pb-BoLM0X4K.mjs → service_pb-BwZRiNug.mjs} +2 -2
  43. package/dist/{service_pb-BoLM0X4K.mjs.map → service_pb-BwZRiNug.mjs.map} +1 -1
  44. package/dist/{service_pb-r1T7kpJc.mjs → service_pb-wRkxUta6.mjs} +1 -1
  45. package/dist/types/auth.generated.d.mts +14 -2
  46. package/dist/types/executor.generated.d.mts +19 -0
  47. package/dist/types/http-adapter.generated.d.mts +5 -0
  48. package/dist/types/idp.generated.d.mts +30 -0
  49. package/dist/types/resolver.generated.d.mts +28 -2
  50. package/dist/types/tailordb.generated.d.mts +15 -1
  51. package/dist/vitest/environment.mjs +1 -1
  52. package/dist/vitest/index.d.mts +4 -2
  53. package/dist/vitest/index.mjs +83 -2
  54. package/dist/vitest/index.mjs.map +1 -1
  55. package/dist/vitest/mock.d.mts +2 -1
  56. package/dist/vitest/mocks/file.d.mts +1 -1
  57. package/dist/vitest/mocks/logger.d.mts +45 -0
  58. package/dist/vitest/setup.mjs +1 -1
  59. package/dist/{workspace_resource_pb-Db3fv68L.mjs → workspace_resource_pb-UGK1SSn_.mjs} +7 -2
  60. package/dist/{workspace_resource_pb-Db3fv68L.mjs.map → workspace_resource_pb-UGK1SSn_.mjs.map} +1 -1
  61. package/docs/configuration.md +3 -1
  62. package/docs/runtime.md +4 -0
  63. package/docs/services/resolver.md +54 -0
  64. package/docs/testing.md +23 -2
  65. package/package.json +11 -6
  66. package/dist/application-C1d52JP9.mjs.map +0 -1
  67. package/dist/application-Nlh9BHQf.mjs +0 -3
  68. package/dist/logger-BwS4ppwO.mjs.map +0 -1
  69. package/dist/register-typescript-runtime-Bd4bcLbW.mjs.map +0 -1
  70. package/dist/service-Cg7Qibit.mjs +0 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @tailor-platform/sdk
2
2
 
3
+ ## 1.82.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#1866](https://github.com/tailor-platform/sdk/pull/1866) [`1ae2485`](https://github.com/tailor-platform/sdk/commit/1ae24854f049ac51036842bacf4f35eb74ecd50c) Thanks [@toiroakr](https://github.com/toiroakr)! - `logLevel` now also controls `logger.*` calls (from `@tailor-platform/sdk/runtime`) in bundled functions, in addition to `console.*`. `logger.debug`/`logger.info`/`logger.warn`/`logger.error` are dropped at the same thresholds as their `console` counterparts.
8
+
9
+ ### Patch Changes
10
+
11
+ - [#1848](https://github.com/tailor-platform/sdk/pull/1848) [`6f16760`](https://github.com/tailor-platform/sdk/commit/6f167606f01d3eacf157e81f7b7f4c6026b2dc99) Thanks [@toiroakr](https://github.com/toiroakr)! - Replaced the `table` dependency (heavy transitive deps, low OpenSSF Scorecard) with an in-house single-line box-drawing table renderer used by the CLI's tabular output (`logger.out`, `formatTable`/`formatKeyValueTable`/`formatTableWithHeaders`). Column width calculation now uses the small, dependency-free `get-east-asian-width` package for correct alignment with full-width (CJK) characters. No user-facing behavior change is expected.
12
+
13
+ ## 1.81.0
14
+
15
+ ### Minor Changes
16
+
17
+ - [#1824](https://github.com/tailor-platform/sdk/pull/1824) [`617a263`](https://github.com/tailor-platform/sdk/commit/617a2632ae50f9b4db8e436d1da4c4888c907a58) Thanks [@haru0017](https://github.com/haru0017)! - Add a `logger` API for structured logging from Tailor Platform functions, exposing `debug`, `info`, `warn`, `error`, and `setAttributes`. The message is written to standard output, and the full entry with its attributes is exported over OpenTelemetry, where the attributes are queryable. Attribute values are typed to what OpenTelemetry can carry (`string`, `number`, `boolean`, and homogeneous arrays of those).
18
+
19
+ - [#1718](https://github.com/tailor-platform/sdk/pull/1718) [`d688c30`](https://github.com/tailor-platform/sdk/commit/d688c303be1b6693a36b50a03d52c670c05d035a) Thanks [@toiroakr](https://github.com/toiroakr)! - Add `permission` field to `createResolver` for declaring a resolver's access requirement, using the same `conditions`/`permit` policy notation as TailorDB's `.permission()` (restricted to `user` operands, e.g. `permission: [{ conditions: [[{ user: "_loggedIn" }, "=", true]], permit: true }]`). Rejects non-matching callers before `body` runs. At least one `permit: true` policy is required (deny by default, granted only by a match); a matching `permit: false` policy always overrides that grant, for carving out an explicit exception. `permission: "allowAnonymous"` explicitly documents that anonymous callers are allowed. Omitting `permission` keeps prior behavior unchanged. `tailor-sdk function test-run` enforces the same guard.
20
+
21
+ ### Patch Changes
22
+
23
+ - [#1797](https://github.com/tailor-platform/sdk/pull/1797) [`93c1659`](https://github.com/tailor-platform/sdk/commit/93c16590eb21537ded9272ec12ecc683b61de04e) Thanks [@toiroakr](https://github.com/toiroakr)! - Fix deploy reporting spurious updates on every run: TailorDB types no longer drift when the platform proto gains new fields, IdP services without an explicit userAuthPolicy no longer drift against the platform's default password policy, and deploys with pending migrations no longer silently skip type changes in namespaces that have no migrations
24
+
25
+ - [#1842](https://github.com/tailor-platform/sdk/pull/1842) [`b19c22b`](https://github.com/tailor-platform/sdk/commit/b19c22bd8a22c8ec79a5f02545222706101926c6) Thanks [@toiroakr](https://github.com/toiroakr)! - fix(deps): update transitive dependency fast-uri to 3.1.4 [security]
26
+
27
+ - [#1822](https://github.com/tailor-platform/sdk/pull/1822) [`bcfc9ea`](https://github.com/tailor-platform/sdk/commit/bcfc9ea550744c9481fb29d8ed1629851fc0b1f0) Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update dependency execa to v10
28
+
29
+ - [#1826](https://github.com/tailor-platform/sdk/pull/1826) [`bc85e4a`](https://github.com/tailor-platform/sdk/commit/bc85e4a72e25a9d0e0dadd7e2fae3a7be4d1ce59) Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update oxc
30
+
3
31
  ## 1.80.1
4
32
 
5
33
  ### Patch Changes
@@ -0,0 +1,3 @@
1
+ import { n as generatePluginFilesIfNeeded, r as loadApplication, t as defineApplication } from "./application-CVeA53ok.mjs";
2
+
3
+ export { defineApplication, generatePluginFilesIfNeeded };
@@ -1,7 +1,7 @@
1
1
  import { n as isSdkBranded } from "./brand-Eo4pLXPJ.mjs";
2
2
  import { t as assertDefined } from "./assert-DBxo8jPo.mjs";
3
- import { a as parseBoolean, n as logger, r as styles } from "./logger-BwS4ppwO.mjs";
4
- import { a as TailorFieldSchema, i as AuthInvokerSchema, n as ExecutorSchema, o as loadFilesWithIgnores, r as AuthConfigSchema, s as functionSchema, t as createExecutorService } from "./service-CDPatibu.mjs";
3
+ import { a as parseBoolean, n as logger, r as styles } from "./logger-CXQq9YIp.mjs";
4
+ import { a as TailorFieldSchema, i as AuthInvokerSchema, n as ExecutorSchema, o as loadFilesWithIgnores, r as AuthConfigSchema, s as functionSchema, t as createExecutorService } from "./service-B0MaodSg.mjs";
5
5
  import { t as multiline } from "./multiline-sfHpTZZK.mjs";
6
6
  import { t as isPluginGeneratedType } from "./type-source-DH_LH20p.mjs";
7
7
  import { t as userAgent } from "./user-agent-DX2Jnw0-.mjs";
@@ -180,7 +180,7 @@ function initOAuth2Client(config) {
180
180
  */
181
181
  async function initOperatorClient(accessToken, config) {
182
182
  const platformConfig = config ?? getPlatformConfigForToken(accessToken);
183
- const [{ createTracingInterceptor }, { OperatorService }] = await Promise.all([import("./interceptor-D-q1rvRl.mjs"), import("./service_pb-r1T7kpJc.mjs")]);
183
+ const [{ createTracingInterceptor }, { OperatorService }] = await Promise.all([import("./interceptor-D-q1rvRl.mjs"), import("./service_pb-wRkxUta6.mjs")]);
184
184
  const interceptors = [
185
185
  await userAgentInterceptor(),
186
186
  await bearerTokenInterceptor(accessToken),
@@ -260,7 +260,7 @@ function retryInterceptor() {
260
260
  logger.debug(`retry: ${req.method.name} returned AlreadyExists on attempt ${i + 1}; treating as success (prior attempt likely committed)`);
261
261
  return synthesizeEmptyUnaryResponse(req);
262
262
  }
263
- const { reportCrash } = await import("./crashreport-BafWvjjX.mjs");
263
+ const { reportCrash } = await import("./crashreport-ecqnz51B.mjs");
264
264
  await reportCrash(error, "handledError");
265
265
  }
266
266
  if (req.method.name !== "CreateWorkspace" && isRetirable(error, req.method.idempotency)) {
@@ -2057,20 +2057,36 @@ const DEBUG_LEVEL_CONSOLE_METHODS = [
2057
2057
  ];
2058
2058
  const WARN_LEVEL_CONSOLE_METHODS = ["console.warn"];
2059
2059
  const ERROR_LEVEL_CONSOLE_METHODS = ["console.error"];
2060
+ const DEBUG_LEVEL_LOGGER_METHODS = ["globalThis.tailor.logger.debug"];
2061
+ const INFO_LEVEL_LOGGER_METHODS = ["globalThis.tailor.logger.info"];
2062
+ const WARN_LEVEL_LOGGER_METHODS = ["globalThis.tailor.logger.warn"];
2063
+ const ERROR_LEVEL_LOGGER_METHODS = ["globalThis.tailor.logger.error"];
2060
2064
  const MANUAL_PURE_FUNCTIONS_BY_LOG_LEVEL = {
2061
2065
  DEBUG: [],
2062
- INFO: DEBUG_LEVEL_CONSOLE_METHODS,
2063
- WARN: [...DEBUG_LEVEL_CONSOLE_METHODS, ...INFO_LEVEL_CONSOLE_METHODS],
2066
+ INFO: [...DEBUG_LEVEL_CONSOLE_METHODS, ...DEBUG_LEVEL_LOGGER_METHODS],
2067
+ WARN: [
2068
+ ...DEBUG_LEVEL_CONSOLE_METHODS,
2069
+ ...INFO_LEVEL_CONSOLE_METHODS,
2070
+ ...DEBUG_LEVEL_LOGGER_METHODS,
2071
+ ...INFO_LEVEL_LOGGER_METHODS
2072
+ ],
2064
2073
  ERROR: [
2065
2074
  ...DEBUG_LEVEL_CONSOLE_METHODS,
2066
2075
  ...INFO_LEVEL_CONSOLE_METHODS,
2067
- ...WARN_LEVEL_CONSOLE_METHODS
2076
+ ...WARN_LEVEL_CONSOLE_METHODS,
2077
+ ...DEBUG_LEVEL_LOGGER_METHODS,
2078
+ ...INFO_LEVEL_LOGGER_METHODS,
2079
+ ...WARN_LEVEL_LOGGER_METHODS
2068
2080
  ],
2069
2081
  SILENT: [
2070
2082
  ...DEBUG_LEVEL_CONSOLE_METHODS,
2071
2083
  ...INFO_LEVEL_CONSOLE_METHODS,
2072
2084
  ...WARN_LEVEL_CONSOLE_METHODS,
2073
- ...ERROR_LEVEL_CONSOLE_METHODS
2085
+ ...ERROR_LEVEL_CONSOLE_METHODS,
2086
+ ...DEBUG_LEVEL_LOGGER_METHODS,
2087
+ ...INFO_LEVEL_LOGGER_METHODS,
2088
+ ...WARN_LEVEL_LOGGER_METHODS,
2089
+ ...ERROR_LEVEL_LOGGER_METHODS
2074
2090
  ]
2075
2091
  };
2076
2092
  function normalizeBundleLogLevel(value) {
@@ -3918,6 +3934,111 @@ function buildExecutorArgsExpr(triggerKind, env) {
3918
3934
  function buildResolverOperationHookExpr(env) {
3919
3935
  return `({ ...context.pipeline, input: context.args, user: ${tailorUserMap}, env: ${JSON.stringify(env)} });`;
3920
3936
  }
3937
+ function isSingleResolverCondition(conditions) {
3938
+ return conditions.length === 3 && typeof conditions[1] === "string";
3939
+ }
3940
+ function resolverPermissionOperandExpr(operand) {
3941
+ if (typeof operand === "object") {
3942
+ if (operand.user === "_loggedIn") return `(context.user.type !== "")`;
3943
+ if (operand.user === "id") return `context.user.id`;
3944
+ return `context.user.attributes?.[${JSON.stringify(operand.user)}]`;
3945
+ }
3946
+ return JSON.stringify(operand);
3947
+ }
3948
+ function isArbitraryAttributeOperand(operand) {
3949
+ return typeof operand === "object" && operand.user !== "_loggedIn" && operand.user !== "id";
3950
+ }
3951
+ function resolverPermissionConditionExpr(condition) {
3952
+ const [left, operator, right] = condition;
3953
+ const leftExpr = resolverPermissionOperandExpr(left);
3954
+ const rightExpr = resolverPermissionOperandExpr(right);
3955
+ if (operator === "!=") {
3956
+ const userOperandExpr = isArbitraryAttributeOperand(left) ? leftExpr : isArbitraryAttributeOperand(right) ? rightExpr : void 0;
3957
+ if (userOperandExpr) return `(${userOperandExpr} !== undefined && ${leftExpr} !== ${rightExpr})`;
3958
+ }
3959
+ return `(${leftExpr} ${operator === "=" ? "===" : "!=="} ${rightExpr})`;
3960
+ }
3961
+ function resolverPermissionPolicyExpr(policy) {
3962
+ const conditions = isSingleResolverCondition(policy.conditions) ? [policy.conditions] : policy.conditions;
3963
+ if (conditions.length === 0) throw new Error("Resolver permission policy must have at least one condition, got an empty array.");
3964
+ return conditions.map(resolverPermissionConditionExpr).join(" && ");
3965
+ }
3966
+ /**
3967
+ * Build a JS object literal capturing whether `policy` matched and its
3968
+ * (possibly empty) description, for runtime denial-reason attribution.
3969
+ * @param policy - The policy to compile
3970
+ * @returns A JS object literal expression: `{ matched, description }`
3971
+ */
3972
+ function policyEntryExpr(policy) {
3973
+ return `{ matched: ${resolverPermissionPolicyExpr(policy)}, description: ${JSON.stringify(policy.description ?? "")} }`;
3974
+ }
3975
+ /**
3976
+ * Build the permission guard statement injected at resolver entry.
3977
+ *
3978
+ * Rejects the call with `TailorErrorMessage` when the caller doesn't match
3979
+ * `permission`, evaluated against `context.user` — the original caller,
3980
+ * unaffected by `authInvoker`. `permission` is deny-by-default: a caller is
3981
+ * granted only by a matching `permit: true` policy, and a matching
3982
+ * `permit: false` policy always overrides that grant. The thrown message only
3983
+ * includes the description(s) of the policy/policies that actually caused the
3984
+ * denial.
3985
+ *
3986
+ * The schema requires at least one `permit: true` policy (an array of only
3987
+ * `permit: false` policies is rejected at build time), so `allowPolicies` is
3988
+ * never empty here for schema-valid input; this function still handles that
3989
+ * case defensively since it also runs against test-authored raw shapes.
3990
+ * @param permission - The resolver's `permission` config
3991
+ * @returns A JS statement, or `undefined` when `permission` is omitted or `"allowAnonymous"`
3992
+ */
3993
+ function buildResolverPermissionGuardExpr(permission) {
3994
+ if (!permission || permission === "allowAnonymous") return;
3995
+ if (permission.length === 0) throw new Error("Resolver permission must have at least one policy, got an empty array.");
3996
+ const denyPolicies = permission.filter((policy) => policy.permit === false);
3997
+ const allowPolicies = permission.filter((policy) => policy.permit !== false);
3998
+ return `{
3999
+ const $denyPolicies = ${`[${denyPolicies.map(policyEntryExpr).join(", ")}]`};
4000
+ const $allowPolicies = ${`[${allowPolicies.map(policyEntryExpr).join(", ")}]`};
4001
+ const $matchedDeny = $denyPolicies.filter((p) => p.matched);
4002
+ const $anyAllowMatched = $allowPolicies.some((p) => p.matched);
4003
+ if ($matchedDeny.length > 0 || ($allowPolicies.length > 0 && !$anyAllowMatched)) {
4004
+ const $reasons = ($matchedDeny.length > 0 ? $matchedDeny : $allowPolicies)
4005
+ .map((p) => p.description)
4006
+ .filter(Boolean);
4007
+ throw new TailorErrorMessage($reasons.length > 0 ? "access denied: " + $reasons.join("; ") : "access denied");
4008
+ }
4009
+ }`;
4010
+ }
4011
+ /**
4012
+ * Build the permission guard and input-validation statements shared by every
4013
+ * resolver entry wrapper (production bundling and `function test-run`).
4014
+ *
4015
+ * Kept as a single generator so a resolver-wrapping behavior (like the
4016
+ * permission guard) can't be added to one entry-point template and forgotten
4017
+ * in the other. References `context.user`, `context.input`, and
4018
+ * `_internalResolver` — the caller's wrapper must bind a `context` object
4019
+ * with `user`/`input` properties before inlining this expression.
4020
+ * @param permission - The resolver's `permission` config
4021
+ * @returns A JS statement block to inline before calling `_internalResolver.body(...)`
4022
+ */
4023
+ function buildResolverPermissionAndInputCheckExpr(permission) {
4024
+ return `
4025
+ ${buildResolverPermissionGuardExpr(permission) ?? ""}
4026
+ if (_internalResolver.input) {
4027
+ const result = t.object(_internalResolver.input).parse({
4028
+ value: context.input,
4029
+ data: context.input,
4030
+ user: context.user,
4031
+ });
4032
+
4033
+ if (result.issues) {
4034
+ throw new TailorErrors(result.issues.map(issue => ({
4035
+ message: issue.message,
4036
+ path: issue.path ?? [],
4037
+ })));
4038
+ }
4039
+ }
4040
+ `;
4041
+ }
3921
4042
 
3922
4043
  //#endregion
3923
4044
  //#region src/cli/services/executor/loader.ts
@@ -4338,6 +4459,42 @@ function isAsyncFunction(fn) {
4338
4459
  //#endregion
4339
4460
  //#region src/parser/service/resolver/schema.ts
4340
4461
  const QueryTypeSchema = z.union([z.literal("query"), z.literal("mutation")]).describe("GraphQL operation type");
4462
+ const ResolverPermissionOperandSchema = z.union([
4463
+ z.object({ user: z.string() }).strict(),
4464
+ z.string(),
4465
+ z.boolean()
4466
+ ]);
4467
+ const ResolverPermissionOperatorSchema = z.union([z.literal("="), z.literal("!=")]);
4468
+ const isUserOperand = (operand) => typeof operand === "object";
4469
+ const KNOWN_USER_OPERAND_TYPES = {
4470
+ _loggedIn: "boolean",
4471
+ id: "string"
4472
+ };
4473
+ const operandTypeMismatch = (userOperand, otherOperand) => {
4474
+ if (typeof userOperand !== "object") return;
4475
+ const expected = KNOWN_USER_OPERAND_TYPES[userOperand.user];
4476
+ if (expected === void 0 || typeof otherOperand === "object" || typeof otherOperand === expected) return;
4477
+ return {
4478
+ key: userOperand.user,
4479
+ expected
4480
+ };
4481
+ };
4482
+ const ResolverPermissionConditionSchema = z.tuple([
4483
+ ResolverPermissionOperandSchema,
4484
+ ResolverPermissionOperatorSchema,
4485
+ ResolverPermissionOperandSchema
4486
+ ]).refine(([left, , right]) => isUserOperand(left) !== isUserOperand(right), "Resolver permission condition must reference a `user` operand on exactly one side (comparing two `user` operands to each other can match on `undefined === undefined`)").superRefine(([left, , right], ctx) => {
4487
+ for (const mismatch of [operandTypeMismatch(left, right), operandTypeMismatch(right, left)]) if (mismatch) ctx.addIssue({
4488
+ code: "custom",
4489
+ message: `\`${mismatch.key}\` must compare to a ${mismatch.expected}`
4490
+ });
4491
+ }).readonly();
4492
+ const ResolverPermissionPolicySchema = z.object({
4493
+ conditions: z.union([ResolverPermissionConditionSchema, z.array(ResolverPermissionConditionSchema).min(1, "Resolver permission policy must have at least one condition").readonly()]),
4494
+ permit: z.boolean(),
4495
+ description: z.string().optional().describe("Reason recorded for this policy, used in the access-denied error message")
4496
+ });
4497
+ const ResolverPermissionSchema = z.union([z.array(ResolverPermissionPolicySchema).min(1, "Resolver permission must have at least one policy").refine((policies) => policies.some((policy) => policy.permit === true), "Resolver permission must include at least one `permit: true` policy — a policy array with only `permit: false` policies still lets any caller through by simply not authenticating, since none of the deny conditions apply to a caller with no user attributes at all").readonly(), z.literal("allowAnonymous")]).describe("Access requirement for this resolver, evaluated against the original caller (unaffected by `authInvoker`) before `body` runs. \"allowAnonymous\" documents that anonymous callers are allowed. Omitted (default): unchanged, anonymous callers can reach the resolver");
4341
4498
  const ResolverSchema = z.object({
4342
4499
  operation: QueryTypeSchema.describe("GraphQL operation type (query or mutation)"),
4343
4500
  name: z.string().describe("Resolver name"),
@@ -4346,7 +4503,8 @@ const ResolverSchema = z.object({
4346
4503
  body: functionSchema.describe("Resolver implementation function"),
4347
4504
  output: TailorFieldSchema.describe("Output field definition"),
4348
4505
  publishEvents: z.boolean().optional().describe("Enable publishing events from this resolver"),
4349
- authInvoker: AuthInvokerSchema.optional().describe("Machine user to execute this resolver as")
4506
+ authInvoker: AuthInvokerSchema.optional().describe("Machine user to execute this resolver as"),
4507
+ permission: ResolverPermissionSchema.optional()
4350
4508
  });
4351
4509
 
4352
4510
  //#endregion
@@ -4399,7 +4557,8 @@ async function bundleResolvers(namespace, config, baseDir, triggerContext, cache
4399
4557
  }
4400
4558
  resolvers.push({
4401
4559
  name: resolver.name,
4402
- sourceFile: file
4560
+ sourceFile: file,
4561
+ permission: resolver.permission
4403
4562
  });
4404
4563
  }
4405
4564
  const tsconfig = await resolveTSConfigWithFallback(baseDir);
@@ -4431,21 +4590,7 @@ async function bundleSingleResolver(namespace, resolver, tsconfig, triggerContex
4431
4590
 
4432
4591
  const $tailor_resolver_body = async (context) => {
4433
4592
  const invoker = ${INVOKER_EXPR};
4434
- if (_internalResolver.input) {
4435
- const result = t.object(_internalResolver.input).parse({
4436
- value: context.input,
4437
- data: context.input,
4438
- user: context.user,
4439
- });
4440
-
4441
- if (result.issues) {
4442
- throw new TailorErrors(result.issues.map(issue => ({
4443
- message: issue.message,
4444
- path: issue.path ?? [],
4445
- })));
4446
- }
4447
- }
4448
-
4593
+ ${buildResolverPermissionAndInputCheckExpr(resolver.permission)}
4449
4594
  return _internalResolver.body({ ...context, invoker });
4450
4595
  };
4451
4596
 
@@ -5611,5 +5756,5 @@ async function loadApplication(params) {
5611
5756
  }
5612
5757
 
5613
5758
  //#endregion
5614
- export { fetchAll as A, initOAuth2Client as B, hasGenerationHooks as C, hashFile as D, hashContent as E, fetchUserInfo as F, resolveStaticWebsiteUrls as G, isDefaultPlatform as H, getConsoleBaseUrl as I, LOG_LEVELS as J, byName as K, getOAuth2ClientId as L, fetchMachineUserToken as M, fetchPaged as N, closeConnectionPool as O, fetchPlatformMachineUserToken as P, getOrNull as R, getPluginGenerationDependencies as S, getDistDir as T, normalizeBaseUrl as U, initOperatorClient as V, rememberPlatformConfigForToken as W, resolveTSConfigWithFallback as _, resolveInlineSourcemap as a, createLogLevelTreeshakeOptions as b, ResolverSchema as c, buildExecutorArgsExpr as d, buildResolverOperationHookExpr as f, stringifyFunction as g, TailorDBTypeSchema as h, resolverBundleKey as i, fetchAllTolerant as j, defaultPlatformBaseUrl as k, HTTP_METHODS as l, assertUniqueTailorDBTypeNamesWithExternal as m, generatePluginFilesIfNeeded as n, WorkflowJobFunctionExecutionPolicySchema as o, assertUniqueLocalTailorDBTypeNames as p, createApplyLimiter as q, loadApplication as r, WorkflowJobSchema as s, defineApplication as t, INVOKER_EXPR as u, platformBundleDefinePlugin as v, createBundleCache as w, resolveBundleLogLevel as x, composeFunctionTreeshakeOptions as y, getPlatformBaseUrl as z };
5615
- //# sourceMappingURL=application-C1d52JP9.mjs.map
5759
+ export { defaultPlatformBaseUrl as A, getPlatformBaseUrl as B, getPluginGenerationDependencies as C, hashContent as D, getDistDir as E, fetchPlatformMachineUserToken as F, rememberPlatformConfigForToken as G, initOperatorClient as H, fetchUserInfo as I, createApplyLimiter as J, resolveStaticWebsiteUrls as K, getConsoleBaseUrl as L, fetchAllTolerant as M, fetchMachineUserToken as N, hashFile as O, fetchPaged as P, getOAuth2ClientId as R, resolveBundleLogLevel as S, createBundleCache as T, isDefaultPlatform as U, initOAuth2Client as V, normalizeBaseUrl as W, LOG_LEVELS as Y, stringifyFunction as _, resolveInlineSourcemap as a, composeFunctionTreeshakeOptions as b, ResolverSchema as c, buildExecutorArgsExpr as d, buildResolverOperationHookExpr as f, TailorDBTypeSchema as g, assertUniqueTailorDBTypeNamesWithExternal as h, resolverBundleKey as i, fetchAll as j, closeConnectionPool as k, HTTP_METHODS as l, assertUniqueLocalTailorDBTypeNames as m, generatePluginFilesIfNeeded as n, WorkflowJobFunctionExecutionPolicySchema as o, buildResolverPermissionAndInputCheckExpr as p, byName as q, loadApplication as r, WorkflowJobSchema as s, defineApplication as t, INVOKER_EXPR as u, resolveTSConfigWithFallback as v, hasGenerationHooks as w, createLogLevelTreeshakeOptions as x, platformBundleDefinePlugin as y, getOrNull as z };
5760
+ //# sourceMappingURL=application-CVeA53ok.mjs.map