@concavejs/docstore-better-sqlite3 0.0.1-alpha.15 → 0.0.1-alpha.16

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 (2) hide show
  1. package/dist/index.js +724 -469
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1051,19 +1051,7 @@ function hexToString(hex) {
1051
1051
  const buffer = hexToArrayBuffer(hex);
1052
1052
  return new TextDecoder().decode(buffer);
1053
1053
  }
1054
- function deserializeDeveloperId(developerId) {
1055
- if (!developerId) {
1056
- return null;
1057
- }
1058
- for (const separator of [DOC_ID_SEPARATOR, LEGACY_DOC_ID_SEPARATOR]) {
1059
- const parts = developerId.split(separator);
1060
- if (parts.length === 2 && parts[0] && parts[1]) {
1061
- return { table: parts[0], internalId: parts[1] };
1062
- }
1063
- }
1064
- return null;
1065
- }
1066
- var BYTE_TO_HEX, HEX_TO_NIBBLE, DOC_ID_SEPARATOR = ":", LEGACY_DOC_ID_SEPARATOR = ";";
1054
+ var BYTE_TO_HEX, HEX_TO_NIBBLE;
1067
1055
  var init_utils = __esm(() => {
1068
1056
  BYTE_TO_HEX = [];
1069
1057
  for (let i2 = 0;i2 < 256; i2++) {
@@ -3311,7 +3299,7 @@ async function listSystemFunctions(options = {}) {
3311
3299
  const listing = filteredListings[i2];
3312
3300
  const result = analysisResults[i2];
3313
3301
  if (result.status === "rejected") {
3314
- if (!isNpmPackageError(result.reason)) {
3302
+ if (!isExpectedNonFunctionModuleLoadError(result.reason)) {
3315
3303
  console.warn(`Failed to analyze module "${listing.path}":`, result.reason);
3316
3304
  }
3317
3305
  continue;
@@ -3472,7 +3460,10 @@ async function discoverCronSpecs(options = {}) {
3472
3460
  }
3473
3461
  return cronSpecs;
3474
3462
  }
3475
- function isNpmPackageError(error) {
3463
+ function isExpectedNonFunctionModuleLoadError(error) {
3464
+ return isNpmPackageResolutionError(error) || isStubbedComponentDependencyError(error);
3465
+ }
3466
+ function isNpmPackageResolutionError(error) {
3476
3467
  if (!(error instanceof Error))
3477
3468
  return false;
3478
3469
  const causes = error.causes;
@@ -3488,6 +3479,15 @@ function isNpmPackageError(error) {
3488
3479
  return !modulePath.startsWith(".") && !modulePath.startsWith("/");
3489
3480
  });
3490
3481
  }
3482
+ function isStubbedComponentDependencyError(error) {
3483
+ if (!(error instanceof Error))
3484
+ return false;
3485
+ if (error.message.includes("could not be resolved while bundling component modules") && error.message.includes("only an error if this module is loaded at runtime")) {
3486
+ return true;
3487
+ }
3488
+ const causes = error.causes;
3489
+ return Array.isArray(causes) && causes.some((cause) => isStubbedComponentDependencyError(cause));
3490
+ }
3491
3491
  var moduleAnalysisCache, moduleLoaderApiPromise = null, unsubscribeModuleLoader = null;
3492
3492
  var init_function_introspection = __esm(() => {
3493
3493
  init_analysis();
@@ -5415,6 +5415,10 @@ function parseBoolean(value) {
5415
5415
  return;
5416
5416
  return value.toLowerCase() === "true" || value === "1";
5417
5417
  }
5418
+ function isDevEnvironment(env) {
5419
+ const environment = getEnvValue("ENVIRONMENT", env) ?? getEnvValue("CONCAVE_ENVIRONMENT", env) ?? getEnvValue("NODE_ENV", env);
5420
+ return environment === "development" || parseBoolean(getEnvValue("CONCAVE_DEV", env)) === true;
5421
+ }
5418
5422
  function parseNumber(value) {
5419
5423
  if (!value)
5420
5424
  return;
@@ -5424,8 +5428,7 @@ function parseNumber(value) {
5424
5428
  function resolveAdminAuthConfigFromEnv(env) {
5425
5429
  const token = getEnvValue("ADMIN_TOKEN", env) ?? getEnvValue("CONCAVE_ADMIN_TOKEN", env) ?? getEnvValue("CONCAVE_ADMIN_KEY", env);
5426
5430
  const allowInsecure = parseBoolean(getEnvValue("CONCAVE_ALLOW_INSECURE_ADMIN", env)) ?? parseBoolean(getEnvValue("ALLOW_INSECURE_ADMIN", env));
5427
- const environment = getEnvValue("ENVIRONMENT", env) ?? getEnvValue("CONCAVE_ENVIRONMENT", env) ?? getEnvValue("NODE_ENV", env);
5428
- const allowInsecureFromEnv = allowInsecure ?? environment === "development";
5431
+ const allowInsecureFromEnv = allowInsecure ?? isDevEnvironment(env);
5429
5432
  if (!token && !allowInsecureFromEnv) {
5430
5433
  return;
5431
5434
  }
@@ -5437,8 +5440,7 @@ function resolveAdminAuthConfigFromEnv(env) {
5437
5440
  function resolveSystemAuthConfigFromEnv(env) {
5438
5441
  const token = getEnvValue("SYSTEM_TOKEN", env) ?? getEnvValue("CONCAVE_SYSTEM_TOKEN", env) ?? getEnvValue("CONCAVE_SYSTEM_KEY", env);
5439
5442
  const allowInsecure = parseBoolean(getEnvValue("CONCAVE_ALLOW_INSECURE_SYSTEM", env)) ?? parseBoolean(getEnvValue("ALLOW_INSECURE_SYSTEM", env));
5440
- const environment = getEnvValue("ENVIRONMENT", env) ?? getEnvValue("CONCAVE_ENVIRONMENT", env) ?? getEnvValue("NODE_ENV", env);
5441
- const allowInsecureFromEnv = allowInsecure ?? environment === "development";
5443
+ const allowInsecureFromEnv = allowInsecure ?? isDevEnvironment(env);
5442
5444
  if (!token && !allowInsecureFromEnv) {
5443
5445
  return;
5444
5446
  }
@@ -5658,35 +5660,35 @@ var init_jwt = __esm(() => {
5658
5660
 
5659
5661
  // ../core/dist/auth/auth-context.js
5660
5662
  function getAuthContext() {
5661
- return authContext.getStore();
5663
+ return userIdentityContextStorage.getStore();
5662
5664
  }
5663
- function getPrincipal() {
5664
- return principalContext.getStore();
5665
+ function getResolvedAuthContext() {
5666
+ return resolvedAuthContextStorage.getStore();
5665
5667
  }
5666
- async function runWithAuth(auth, fn, principal) {
5667
- return principalContext.run(principal, () => authContext.run(auth, fn));
5668
+ async function runWithAuth(auth, fn, resolvedAuthContext) {
5669
+ return resolvedAuthContextStorage.run(resolvedAuthContext, () => userIdentityContextStorage.run(auth, fn));
5668
5670
  }
5669
- var AUTH_CONTEXT_SYMBOL, PRINCIPAL_CONTEXT_SYMBOL, globalAuthContext, authContext, principalContext;
5671
+ var AUTH_CONTEXT_SYMBOL, RESOLVED_AUTH_CONTEXT_SYMBOL, globalAuthContext, userIdentityContextStorage, resolvedAuthContextStorage;
5670
5672
  var init_auth_context = __esm(() => {
5671
5673
  init_context_storage();
5672
5674
  AUTH_CONTEXT_SYMBOL = Symbol.for("@concavejs/core/auth-context");
5673
- PRINCIPAL_CONTEXT_SYMBOL = Symbol.for("@concavejs/core/principal-context");
5675
+ RESOLVED_AUTH_CONTEXT_SYMBOL = Symbol.for("@concavejs/core/resolved-auth-context");
5674
5676
  globalAuthContext = globalThis;
5675
- authContext = globalAuthContext[AUTH_CONTEXT_SYMBOL] ?? new ContextStorage;
5676
- principalContext = globalAuthContext[PRINCIPAL_CONTEXT_SYMBOL] ?? new ContextStorage;
5677
+ userIdentityContextStorage = globalAuthContext[AUTH_CONTEXT_SYMBOL] ?? new ContextStorage;
5678
+ resolvedAuthContextStorage = globalAuthContext[RESOLVED_AUTH_CONTEXT_SYMBOL] ?? new ContextStorage;
5677
5679
  if (!globalAuthContext[AUTH_CONTEXT_SYMBOL]) {
5678
- globalAuthContext[AUTH_CONTEXT_SYMBOL] = authContext;
5680
+ globalAuthContext[AUTH_CONTEXT_SYMBOL] = userIdentityContextStorage;
5679
5681
  }
5680
- if (!globalAuthContext[PRINCIPAL_CONTEXT_SYMBOL]) {
5681
- globalAuthContext[PRINCIPAL_CONTEXT_SYMBOL] = principalContext;
5682
+ if (!globalAuthContext[RESOLVED_AUTH_CONTEXT_SYMBOL]) {
5683
+ globalAuthContext[RESOLVED_AUTH_CONTEXT_SYMBOL] = resolvedAuthContextStorage;
5682
5684
  }
5683
5685
  });
5684
5686
 
5685
- // ../core/dist/auth/principal.js
5686
- function anonymousPrincipal() {
5687
+ // ../core/dist/auth/resolved-auth-context.js
5688
+ function anonymousAuthContext() {
5687
5689
  return { kind: "none", scopes: [] };
5688
5690
  }
5689
- function userPrincipal(identity, token, tenantId) {
5691
+ function userAuthContext(identity, token, tenantId) {
5690
5692
  const email = identity.email;
5691
5693
  const subject = identity.subject;
5692
5694
  return {
@@ -5698,7 +5700,7 @@ function userPrincipal(identity, token, tenantId) {
5698
5700
  label: email ?? subject
5699
5701
  };
5700
5702
  }
5701
- function adminPrincipal(opts = {}) {
5703
+ function adminAuthContext(opts = {}) {
5702
5704
  return {
5703
5705
  kind: "admin",
5704
5706
  scopes: opts.scopes ?? ["*"],
@@ -5708,7 +5710,7 @@ function adminPrincipal(opts = {}) {
5708
5710
  label: opts.label ?? "admin"
5709
5711
  };
5710
5712
  }
5711
- function systemPrincipal(opts = {}) {
5713
+ function systemAuthContext(opts = {}) {
5712
5714
  return {
5713
5715
  kind: "system",
5714
5716
  scopes: opts.scopes ?? ["*"],
@@ -5717,48 +5719,122 @@ function systemPrincipal(opts = {}) {
5717
5719
  label: opts.label ?? "system"
5718
5720
  };
5719
5721
  }
5720
- function hasCapability(principal, capability) {
5721
- if (principal.kind === "none" || principal.kind === "user") {
5722
+ function hasCapability(authContext, capability) {
5723
+ if (authContext.kind === "none" || authContext.kind === "user") {
5722
5724
  return false;
5723
5725
  }
5724
- if (principal.scopes.includes("*")) {
5726
+ if (authContext.scopes.includes("*")) {
5725
5727
  return true;
5726
5728
  }
5727
- return principal.scopes.includes(capability);
5729
+ return authContext.scopes.includes(capability);
5728
5730
  }
5729
- function canCallInternal(principal) {
5730
- return principal.kind === "admin" || principal.kind === "system" || principal.kind === "service";
5731
+ function canCallInternal(authContext) {
5732
+ return authContext.kind === "admin" || authContext.kind === "system" || authContext.kind === "service";
5731
5733
  }
5732
- function canAccessComponents(principal) {
5733
- return principal.kind === "admin" || principal.kind === "system";
5734
+ function canAccessComponents(authContext) {
5735
+ return authContext.kind === "admin" || authContext.kind === "system";
5734
5736
  }
5735
5737
  function isAuthPrivileged(auth) {
5736
5738
  return auth?.tokenType === "Admin" || auth?.tokenType === "System";
5737
5739
  }
5738
- function legacyAuthContextToPrincipal(authContext2, tenantId) {
5739
- switch (authContext2.tokenType) {
5740
+ function resolvedAuthContextToWireAuthContext(authContext) {
5741
+ switch (authContext.kind) {
5742
+ case "admin":
5743
+ return { tokenType: "Admin", token: authContext.token, userIdentity: authContext.userIdentity };
5744
+ case "system":
5745
+ return { tokenType: "System", token: authContext.token, userIdentity: authContext.userIdentity };
5746
+ case "user":
5747
+ return { tokenType: "User", token: authContext.token, userIdentity: authContext.userIdentity };
5748
+ case "service":
5749
+ return { tokenType: "Admin", token: authContext.token, userIdentity: authContext.userIdentity };
5750
+ default:
5751
+ return { tokenType: "None" };
5752
+ }
5753
+ }
5754
+ function wireAuthContextToResolvedAuthContext(authContext, tenantId) {
5755
+ switch (authContext.tokenType) {
5740
5756
  case "Admin":
5741
- return adminPrincipal({
5742
- token: authContext2.token,
5757
+ return adminAuthContext({
5758
+ token: authContext.token,
5743
5759
  tenantId,
5744
- impersonating: authContext2.userIdentity,
5760
+ impersonating: authContext.userIdentity,
5745
5761
  label: "admin"
5746
5762
  });
5747
5763
  case "System":
5748
- return systemPrincipal({
5749
- token: authContext2.token,
5764
+ return systemAuthContext({
5765
+ token: authContext.token,
5750
5766
  tenantId,
5751
5767
  label: "system"
5752
5768
  });
5753
5769
  case "User":
5754
- if (authContext2.userIdentity) {
5755
- return userPrincipal(authContext2.userIdentity, authContext2.token, tenantId);
5770
+ if (authContext.userIdentity) {
5771
+ return userAuthContext(authContext.userIdentity, authContext.token, tenantId);
5756
5772
  }
5757
- return anonymousPrincipal();
5773
+ return anonymousAuthContext();
5758
5774
  default:
5759
- return anonymousPrincipal();
5775
+ return anonymousAuthContext();
5776
+ }
5777
+ }
5778
+
5779
+ // ../core/dist/auth/execution-auth.js
5780
+ function isResolvedAuthContext(value) {
5781
+ return value !== null && typeof value === "object" && "kind" in value && "scopes" in value && !("tokenType" in value);
5782
+ }
5783
+ function isWireAuthContext(value) {
5784
+ if (value === null || typeof value !== "object" || !("tokenType" in value)) {
5785
+ return false;
5786
+ }
5787
+ const tokenType = value.tokenType;
5788
+ return tokenType === "Admin" || tokenType === "System" || tokenType === "User" || tokenType === "None";
5789
+ }
5790
+ function resolveExecutionAuth(auth, tenantId) {
5791
+ if (isResolvedAuthContext(auth)) {
5792
+ return {
5793
+ authContext: auth,
5794
+ userIdentity: auth.userIdentity,
5795
+ wireAuthContext: resolvedAuthContextToWireAuthContext(auth),
5796
+ executorAuth: resolvedAuthContextToWireAuthContext(auth)
5797
+ };
5798
+ }
5799
+ if (isWireAuthContext(auth)) {
5800
+ const wireAuthContext = normalizeWireAuthContext(auth);
5801
+ return {
5802
+ authContext: wireAuthContextToResolvedAuthContext(wireAuthContext, tenantId),
5803
+ userIdentity: wireAuthContext.userIdentity,
5804
+ wireAuthContext,
5805
+ executorAuth: wireAuthContext
5806
+ };
5807
+ }
5808
+ if (auth) {
5809
+ return {
5810
+ authContext: userAuthContext(auth, undefined, tenantId),
5811
+ userIdentity: auth,
5812
+ executorAuth: auth
5813
+ };
5760
5814
  }
5815
+ return {
5816
+ authContext: anonymousAuthContext(),
5817
+ wireAuthContext: { tokenType: "None" },
5818
+ executorAuth: undefined
5819
+ };
5761
5820
  }
5821
+ function normalizeWireAuthContext(auth) {
5822
+ if (auth.tokenType !== "User" || auth.userIdentity || !auth.token) {
5823
+ return auth;
5824
+ }
5825
+ const userIdentity = identityFromTrustedToken(auth.token);
5826
+ if (!userIdentity) {
5827
+ return auth;
5828
+ }
5829
+ return {
5830
+ ...auth,
5831
+ userIdentity
5832
+ };
5833
+ }
5834
+ var init_execution_auth = __esm(() => {
5835
+ init_jwt();
5836
+ init_auth_context();
5837
+ });
5762
5838
 
5763
5839
  // ../core/dist/auth/auth-resolver.js
5764
5840
  function isLikelyJwt(token) {
@@ -5809,10 +5885,10 @@ class DefaultAuthResolver {
5809
5885
  const token = request.token;
5810
5886
  const tenantId = request.tenantId ?? this.config.tenantId;
5811
5887
  if (!token && hint === "auto") {
5812
- return { principal: anonymousPrincipal() };
5888
+ return { authContext: anonymousAuthContext() };
5813
5889
  }
5814
5890
  if (hint === "None") {
5815
- return { principal: anonymousPrincipal() };
5891
+ return { authContext: anonymousAuthContext() };
5816
5892
  }
5817
5893
  if (hint === "Admin") {
5818
5894
  return this.resolveAdmin(token, request.impersonating, tenantId);
@@ -5835,7 +5911,7 @@ class DefaultAuthResolver {
5835
5911
  if (token) {
5836
5912
  return this.resolveUser(token, tenantId);
5837
5913
  }
5838
- return { principal: anonymousPrincipal() };
5914
+ return { authContext: anonymousAuthContext() };
5839
5915
  }
5840
5916
  isInsecureAdminFallbackEnabled() {
5841
5917
  if (this.config.allowInsecure) {
@@ -5855,13 +5931,13 @@ class DefaultAuthResolver {
5855
5931
  return scoped;
5856
5932
  }
5857
5933
  this.assertAdminToken(token);
5858
- const principal = adminPrincipal({
5934
+ const authContext = adminAuthContext({
5859
5935
  token,
5860
5936
  tenantId,
5861
5937
  impersonating,
5862
5938
  label: "admin"
5863
5939
  });
5864
- return { principal, userIdentity: impersonating };
5940
+ return { authContext, userIdentity: impersonating };
5865
5941
  }
5866
5942
  async resolveSystem(token, impersonating, tenantId) {
5867
5943
  const scoped = await this.tryResolveScopedManagementJwt(token, "System", tenantId, impersonating);
@@ -5869,16 +5945,16 @@ class DefaultAuthResolver {
5869
5945
  return scoped;
5870
5946
  }
5871
5947
  this.assertSystemToken(token);
5872
- const principal = systemPrincipal({
5948
+ const authContext = systemAuthContext({
5873
5949
  token,
5874
5950
  tenantId,
5875
5951
  label: "system"
5876
5952
  });
5877
- return { principal, userIdentity: impersonating };
5953
+ return { authContext, userIdentity: impersonating };
5878
5954
  }
5879
5955
  async resolveUser(token, tenantId) {
5880
5956
  if (!token) {
5881
- return { principal: anonymousPrincipal() };
5957
+ return { authContext: anonymousAuthContext() };
5882
5958
  }
5883
5959
  const providers = this.config.jwtProviders;
5884
5960
  if (providers && providers.length > 0) {
@@ -5886,8 +5962,8 @@ class DefaultAuthResolver {
5886
5962
  for (const providerConfig of providers) {
5887
5963
  try {
5888
5964
  const identity2 = await verifyJwtAndGetIdentity(token, providerConfig);
5889
- const principal2 = userPrincipal(identity2, token, tenantId);
5890
- return { principal: principal2, userIdentity: identity2 };
5965
+ const authContext2 = userAuthContext(identity2, token, tenantId);
5966
+ return { authContext: authContext2, userIdentity: identity2 };
5891
5967
  } catch (error) {
5892
5968
  errors2.push(error instanceof Error ? error : new Error(String(error)));
5893
5969
  }
@@ -5895,8 +5971,8 @@ class DefaultAuthResolver {
5895
5971
  if (this.config.jwtConfig) {
5896
5972
  try {
5897
5973
  const identity2 = await verifyJwtAndGetIdentity(token, this.config.jwtConfig);
5898
- const principal2 = userPrincipal(identity2, token, tenantId);
5899
- return { principal: principal2, userIdentity: identity2 };
5974
+ const authContext2 = userAuthContext(identity2, token, tenantId);
5975
+ return { authContext: authContext2, userIdentity: identity2 };
5900
5976
  } catch (error) {
5901
5977
  errors2.push(error instanceof Error ? error : new Error(String(error)));
5902
5978
  }
@@ -5905,8 +5981,8 @@ class DefaultAuthResolver {
5905
5981
  throw new JWTValidationError("INVALID_TOKEN", `JWT verification failed for all providers: ${messages}`);
5906
5982
  }
5907
5983
  const identity = await verifyJwtAndGetIdentity(token, this.config.jwtConfig);
5908
- const principal = userPrincipal(identity, token, tenantId);
5909
- return { principal, userIdentity: identity };
5984
+ const authContext = userAuthContext(identity, token, tenantId);
5985
+ return { authContext, userIdentity: identity };
5910
5986
  }
5911
5987
  isAdminToken(token) {
5912
5988
  return !!this.config.adminAuth?.token && token === this.config.adminAuth.token;
@@ -6017,24 +6093,24 @@ class DefaultAuthResolver {
6017
6093
  }
6018
6094
  }
6019
6095
  const label = readStringClaim(claims, cfg.labelClaim ?? "email") ?? readStringClaim(claims, "sub") ?? undefined;
6020
- const principalTenantId = tokenTenantId ?? tenantId;
6096
+ const authContextTenantId = tokenTenantId ?? tenantId;
6021
6097
  if (expectedType === "Admin") {
6022
- const principal2 = adminPrincipal({
6098
+ const authContext2 = adminAuthContext({
6023
6099
  token,
6024
- tenantId: principalTenantId,
6100
+ tenantId: authContextTenantId,
6025
6101
  scopes: effectiveScopes,
6026
6102
  impersonating,
6027
6103
  label
6028
6104
  });
6029
- return { principal: principal2, userIdentity: impersonating };
6105
+ return { authContext: authContext2, userIdentity: impersonating };
6030
6106
  }
6031
- const principal = systemPrincipal({
6107
+ const authContext = systemAuthContext({
6032
6108
  token,
6033
- tenantId: principalTenantId,
6109
+ tenantId: authContextTenantId,
6034
6110
  scopes: effectiveScopes,
6035
6111
  label
6036
6112
  });
6037
- return { principal, userIdentity: impersonating };
6113
+ return { authContext, userIdentity: impersonating };
6038
6114
  }
6039
6115
  }
6040
6116
 
@@ -6186,44 +6262,44 @@ var init_auth_resolver = __esm(() => {
6186
6262
 
6187
6263
  // ../core/dist/auth/authorization-policy.js
6188
6264
  class DefaultAuthorizationPolicy {
6189
- authorize(principal, action) {
6265
+ authorize(authContext, action) {
6190
6266
  switch (action.kind) {
6191
6267
  case "call_function":
6192
- return this.authorizeCallFunction(principal, action);
6268
+ return this.authorizeCallFunction(authContext, action);
6193
6269
  case "call_system_function":
6194
- return this.authorizeSystemFunction(principal, action);
6270
+ return this.authorizeSystemFunction(authContext, action);
6195
6271
  case "access_component":
6196
- return this.authorizeComponentAccess(principal, action);
6272
+ return this.authorizeComponentAccess(authContext, action);
6197
6273
  case "management_operation":
6198
- return this.authorizeManagementOp(principal, action);
6274
+ return this.authorizeManagementOp(authContext, action);
6199
6275
  case "custom":
6200
6276
  return deny(`Custom action '${action.name}' not handled by default policy`);
6201
6277
  }
6202
6278
  }
6203
- authorizeCallFunction(principal, action) {
6204
- if (action.isInternal && !canCallInternal(principal)) {
6279
+ authorizeCallFunction(authContext, action) {
6280
+ if (action.isInternal && !canCallInternal(authContext)) {
6205
6281
  return deny("Internal functions require admin, system, or service authentication", "FORBIDDEN_INTERNAL");
6206
6282
  }
6207
- if (action.componentPath && !canAccessComponents(principal)) {
6283
+ if (action.componentPath && !canAccessComponents(authContext)) {
6208
6284
  return deny("Component-scoped function calls require admin or system authentication", "FORBIDDEN_COMPONENT");
6209
6285
  }
6210
6286
  return ALLOWED;
6211
6287
  }
6212
- authorizeSystemFunction(principal, action) {
6213
- if (!canCallInternal(principal)) {
6288
+ authorizeSystemFunction(authContext, action) {
6289
+ if (!canCallInternal(authContext)) {
6214
6290
  return deny(`System function '${action.functionName}' requires admin, system, or service authentication`, "FORBIDDEN_SYSTEM");
6215
6291
  }
6216
6292
  return ALLOWED;
6217
6293
  }
6218
- authorizeComponentAccess(principal, _action) {
6219
- if (!canAccessComponents(principal)) {
6294
+ authorizeComponentAccess(authContext, _action) {
6295
+ if (!canAccessComponents(authContext)) {
6220
6296
  return deny("Component access requires admin or system authentication", "FORBIDDEN_COMPONENT");
6221
6297
  }
6222
6298
  return ALLOWED;
6223
6299
  }
6224
- authorizeManagementOp(principal, action) {
6225
- if (!hasCapability(principal, action.capability)) {
6226
- return deny(`Principal lacks required capability '${action.capability}'` + (action.resource ? ` for resource '${action.resource}'` : ""), "FORBIDDEN_CAPABILITY");
6300
+ authorizeManagementOp(authContext, action) {
6301
+ if (!hasCapability(authContext, action.capability)) {
6302
+ return deny(`ResolvedAuthContext lacks required capability '${action.capability}'` + (action.resource ? ` for resource '${action.resource}'` : ""), "FORBIDDEN_CAPABILITY");
6227
6303
  }
6228
6304
  return ALLOWED;
6229
6305
  }
@@ -6231,8 +6307,8 @@ class DefaultAuthorizationPolicy {
6231
6307
  function deny(reason, code2) {
6232
6308
  return { allowed: false, reason, code: code2 };
6233
6309
  }
6234
- function requireAuthorization(principal, action, policy = defaultAuthorizationPolicy) {
6235
- const decision = policy.authorize(principal, action);
6310
+ function requireAuthorization(authContext, action, policy = defaultAuthorizationPolicy) {
6311
+ const decision = policy.authorize(authContext, action);
6236
6312
  if (!decision.allowed) {
6237
6313
  const err = new Error(decision.reason);
6238
6314
  err.code = decision.code ?? "FORBIDDEN";
@@ -6255,6 +6331,7 @@ var init_auth_config_service = __esm(() => {
6255
6331
  var init_auth = __esm(() => {
6256
6332
  init_jwt();
6257
6333
  init_auth_context();
6334
+ init_execution_auth();
6258
6335
  init_auth_resolver();
6259
6336
  init_authorization_policy();
6260
6337
  init_auth_config_service();
@@ -6353,6 +6430,7 @@ function createTableRegistrySnapshot(tables, partial) {
6353
6430
  fullName: table.fullName,
6354
6431
  isSystem: table.isSystem,
6355
6432
  visibility: table.visibility,
6433
+ state: table.state,
6356
6434
  createdAt: table.createdAt
6357
6435
  })).sort((a, b) => a.tableNumber - b.tableNumber);
6358
6436
  const updatedAt = partial?.updatedAt ?? Date.now();
@@ -6969,11 +7047,11 @@ var init_system_tables = __esm(() => {
6969
7047
 
6970
7048
  // ../core/dist/system/internal.js
6971
7049
  function requireSystemCapability(capability) {
6972
- const principal2 = getPrincipal();
6973
- if (!principal2) {
7050
+ const authContext = getResolvedAuthContext();
7051
+ if (!authContext) {
6974
7052
  throw new Error("System functions require authentication context");
6975
7053
  }
6976
- requireAuthorization(principal2, { kind: "management_operation", capability });
7054
+ requireAuthorization(authContext, { kind: "management_operation", capability });
6977
7055
  }
6978
7056
  function createSystemFunctions(deps) {
6979
7057
  const { query, mutation } = deps;
@@ -8327,8 +8405,8 @@ Path: ${formatPath(path)}
8327
8405
  Value: ${formatValue(value)}
8328
8406
  Validator: v.id("${validator2.tableName}")`);
8329
8407
  }
8330
- const tableName2 = tableNameFromConvexId(value, options);
8331
- if (!tableName2 || !isMatchingValidatorTable(tableName2, validator2.tableName, options.componentPath)) {
8408
+ const tableName = tableNameFromConvexId(value, options);
8409
+ if (!tableName || !isMatchingValidatorTable(tableName, validator2.tableName, options.componentPath)) {
8332
8410
  throw new Error(`Value does not match validator.
8333
8411
  Path: ${formatPath(path)}
8334
8412
  Value: ${formatValue(value)}
@@ -8336,14 +8414,10 @@ Validator: v.id("${validator2.tableName}")`);
8336
8414
  }
8337
8415
  return;
8338
8416
  }
8339
- const tableName = tableNameFromId(value);
8340
- if (!tableName || !isMatchingValidatorTable(tableName, validator2.tableName, options.componentPath)) {
8341
- throw new Error(`Value does not match validator.
8417
+ throw new Error(`Value does not match validator.
8342
8418
  Path: ${formatPath(path)}
8343
8419
  Value: ${formatValue(value)}
8344
8420
  Validator: v.id("${validator2.tableName}")`);
8345
- }
8346
- return;
8347
8421
  }
8348
8422
  case "array": {
8349
8423
  if (!Array.isArray(value)) {
@@ -8412,13 +8486,6 @@ Validator: v.object({...})`);
8412
8486
  }
8413
8487
  }
8414
8488
  }
8415
- function tableNameFromId(id) {
8416
- const parts = deserializeDeveloperId(id);
8417
- if (!parts) {
8418
- return null;
8419
- }
8420
- return hexToString(parts.table);
8421
- }
8422
8489
  function tableNameFromConvexId(id, options) {
8423
8490
  try {
8424
8491
  const decoded = decodeDocumentId(id);
@@ -8534,7 +8601,6 @@ function isSimpleObject2(value) {
8534
8601
  }
8535
8602
  var ValidatorError, referencedTableNamesCache;
8536
8603
  var init_validator2 = __esm(() => {
8537
- init_utils();
8538
8604
  init_interface2();
8539
8605
  init_module_loader();
8540
8606
  init_id_codec();
@@ -8631,60 +8697,7 @@ var GLOBALS_TABLE_SCHEMA = `
8631
8697
  `;
8632
8698
  // ../core/dist/abstractions/runtime-services.js
8633
8699
  function resolveRuntimeServices(services) {
8634
- if (isResolvedRuntimeServices(services)) {
8635
- return services;
8636
- }
8637
- const storageCapabilities = resolveStorageCapabilities(services);
8638
- return {
8639
- ...services,
8640
- blobstore: storageCapabilities.blobs?.store,
8641
- searchstore: storageCapabilities.search,
8642
- vecstore: storageCapabilities.vector,
8643
- storageCapabilities
8644
- };
8645
- }
8646
- function isResolvedRuntimeServices(services) {
8647
- return "storageCapabilities" in services;
8648
- }
8649
- function resolveStorageCapabilities(services) {
8650
- const blobCapability = resolveBlobCapability(services.capabilities?.blobs);
8651
- const searchCapability = resolveSearchCapability(services.capabilities?.search, services.docstore);
8652
- const vectorCapability = resolveVectorCapability(services.capabilities?.vector, services.docstore);
8653
- return {
8654
- ...blobCapability ? { blobs: blobCapability } : {},
8655
- ...searchCapability ? { search: searchCapability } : {},
8656
- ...vectorCapability ? { vector: vectorCapability } : {}
8657
- };
8658
- }
8659
- function resolveBlobCapability(capability) {
8660
- if (!capability) {
8661
- return;
8662
- }
8663
- if (!isBlobCapabilityObject(capability)) {
8664
- throw new Error("storage.blobstore must be false or an object with a BlobStore in storage.blobstore.store");
8665
- }
8666
- if (capability.consistency !== "atomic" && capability.consistency !== "eventual") {
8667
- throw new Error('storage.blobstore.consistency must be "atomic" or "eventual"');
8668
- }
8669
- return {
8670
- store: capability.store,
8671
- consistency: capability.consistency
8672
- };
8673
- }
8674
- function isBlobCapabilityObject(capability) {
8675
- return typeof capability === "object" && capability !== null && typeof capability.store?.store === "function" && typeof capability.store?.get === "function" && typeof capability.store?.delete === "function" && typeof capability.store?.getUrl === "function";
8676
- }
8677
- function resolveSearchCapability(capability, _docstore) {
8678
- if (capability === false) {
8679
- return;
8680
- }
8681
- return capability;
8682
- }
8683
- function resolveVectorCapability(capability, _docstore) {
8684
- if (capability === false) {
8685
- return;
8686
- }
8687
- return capability;
8700
+ return services;
8688
8701
  }
8689
8702
  // ../core/dist/abstractions/storage-spec.js
8690
8703
  var CAPABILITY_MAP_KEYS = new Set([
@@ -8693,10 +8706,7 @@ var CAPABILITY_MAP_KEYS = new Set([
8693
8706
  "search",
8694
8707
  "vecstore",
8695
8708
  "transaction",
8696
- "close",
8697
- "documents",
8698
- "blobs",
8699
- "vector"
8709
+ "close"
8700
8710
  ]);
8701
8711
 
8702
8712
  // ../core/dist/index.js
@@ -8847,6 +8857,7 @@ init_interface();
8847
8857
  // ../core/dist/queryengine/developer-id.js
8848
8858
  init_utils();
8849
8859
  init_id_codec();
8860
+ var LEGACY_INTERNAL_DOCUMENT_ID_RE = /^([0-9a-fA-F]+):([0-9a-fA-F]{32})$/;
8850
8861
  function parseDeveloperId(developerId) {
8851
8862
  if (isValidDocumentId(developerId)) {
8852
8863
  try {
@@ -8856,13 +8867,11 @@ function parseDeveloperId(developerId) {
8856
8867
  internalId: internalIdToHex(decoded.internalId),
8857
8868
  tableNumber: decoded.tableNumber
8858
8869
  };
8859
- } catch {}
8860
- }
8861
- const parts = deserializeDeveloperId(developerId);
8862
- if (!parts) {
8863
- return null;
8870
+ } catch {
8871
+ return null;
8872
+ }
8864
8873
  }
8865
- return { table: parts.table, internalId: parts.internalId };
8874
+ return parseLegacyInternalDocumentId(developerId);
8866
8875
  }
8867
8876
  async function parseDeveloperIdWithTableRegistry(developerId, tableRegistry) {
8868
8877
  if (isValidDocumentId(developerId)) {
@@ -8896,6 +8905,20 @@ function parseStorageId(storageId) {
8896
8905
  }
8897
8906
  return null;
8898
8907
  }
8908
+ function parseLegacyInternalDocumentId(developerId) {
8909
+ const match = LEGACY_INTERNAL_DOCUMENT_ID_RE.exec(developerId);
8910
+ if (!match) {
8911
+ return null;
8912
+ }
8913
+ const table = match[1].toLowerCase();
8914
+ if (table.length === 0 || table.length % 2 !== 0) {
8915
+ return null;
8916
+ }
8917
+ return {
8918
+ table,
8919
+ internalId: match[2].toLowerCase()
8920
+ };
8921
+ }
8899
8922
  function isTablePlaceholder(table) {
8900
8923
  return table.startsWith("#");
8901
8924
  }
@@ -9026,6 +9049,123 @@ class UncommittedWrites {
9026
9049
  }
9027
9050
  }
9028
9051
 
9052
+ // ../core/dist/transactor/occ-transaction.js
9053
+ init_udf_trace();
9054
+
9055
+ // ../core/dist/limits/transaction-headroom.js
9056
+ init_values();
9057
+ var MEBIBYTE = 1024 * 1024;
9058
+ var TRANSACTION_HEADROOM_LIMITS = {
9059
+ bytesRead: 16 * MEBIBYTE,
9060
+ bytesWritten: 16 * MEBIBYTE,
9061
+ databaseQueries: 4096,
9062
+ documentsRead: 32000,
9063
+ documentsWritten: 16000,
9064
+ functionsScheduled: 1000,
9065
+ scheduledFunctionArgsBytes: 16 * MEBIBYTE
9066
+ };
9067
+ var encoder = new TextEncoder;
9068
+ function remaining(limit, used) {
9069
+ return Math.max(0, limit - used);
9070
+ }
9071
+ function estimateConvexValueBytes(value) {
9072
+ const json = JSON.stringify(convexToJson(value));
9073
+ return encoder.encode(json).byteLength;
9074
+ }
9075
+
9076
+ class TransactionHeadroomTracker {
9077
+ bytesRead = 0;
9078
+ documentsRead = 0;
9079
+ databaseQueries = 0;
9080
+ functionsScheduled = 0;
9081
+ scheduledFunctionArgsBytes = 0;
9082
+ bytesWritten = 0;
9083
+ writtenDocuments = new Map;
9084
+ recordDatabaseQuery(count = 1) {
9085
+ this.databaseQueries += count;
9086
+ }
9087
+ recordRead(value) {
9088
+ this.documentsRead += 1;
9089
+ this.bytesRead += estimateConvexValueBytes(value);
9090
+ }
9091
+ recordReads(values) {
9092
+ for (const value of values) {
9093
+ this.recordRead(value);
9094
+ }
9095
+ }
9096
+ recordScheduledFunction(args) {
9097
+ this.functionsScheduled += 1;
9098
+ this.scheduledFunctionArgsBytes += estimateConvexValueBytes(args);
9099
+ }
9100
+ trackWrittenDocument(documentKey, value) {
9101
+ const nextBytes = estimateConvexValueBytes(value);
9102
+ const previousBytes = this.writtenDocuments.get(documentKey);
9103
+ if (previousBytes !== undefined) {
9104
+ this.bytesWritten -= previousBytes;
9105
+ }
9106
+ this.writtenDocuments.set(documentKey, nextBytes);
9107
+ this.bytesWritten += nextBytes;
9108
+ }
9109
+ snapshot() {
9110
+ return {
9111
+ bytesRead: this.bytesRead,
9112
+ documentsRead: this.documentsRead,
9113
+ databaseQueries: this.databaseQueries,
9114
+ functionsScheduled: this.functionsScheduled,
9115
+ scheduledFunctionArgsBytes: this.scheduledFunctionArgsBytes,
9116
+ bytesWritten: this.bytesWritten,
9117
+ writtenDocuments: new Map(this.writtenDocuments)
9118
+ };
9119
+ }
9120
+ restore(snapshot) {
9121
+ this.bytesRead = snapshot.bytesRead;
9122
+ this.documentsRead = snapshot.documentsRead;
9123
+ this.databaseQueries = snapshot.databaseQueries;
9124
+ this.functionsScheduled = snapshot.functionsScheduled;
9125
+ this.scheduledFunctionArgsBytes = snapshot.scheduledFunctionArgsBytes;
9126
+ this.bytesWritten = snapshot.bytesWritten;
9127
+ this.writtenDocuments.clear();
9128
+ for (const [documentKey, bytes] of snapshot.writtenDocuments) {
9129
+ this.writtenDocuments.set(documentKey, bytes);
9130
+ }
9131
+ }
9132
+ getHeadroom() {
9133
+ return {
9134
+ bytesRead: {
9135
+ used: this.bytesRead,
9136
+ remaining: remaining(TRANSACTION_HEADROOM_LIMITS.bytesRead, this.bytesRead)
9137
+ },
9138
+ bytesWritten: {
9139
+ used: this.bytesWritten,
9140
+ remaining: remaining(TRANSACTION_HEADROOM_LIMITS.bytesWritten, this.bytesWritten)
9141
+ },
9142
+ databaseQueries: {
9143
+ used: this.databaseQueries,
9144
+ remaining: remaining(TRANSACTION_HEADROOM_LIMITS.databaseQueries, this.databaseQueries)
9145
+ },
9146
+ documentsRead: {
9147
+ used: this.documentsRead,
9148
+ remaining: remaining(TRANSACTION_HEADROOM_LIMITS.documentsRead, this.documentsRead)
9149
+ },
9150
+ documentsWritten: {
9151
+ used: this.writtenDocuments.size,
9152
+ remaining: remaining(TRANSACTION_HEADROOM_LIMITS.documentsWritten, this.writtenDocuments.size)
9153
+ },
9154
+ functionsScheduled: {
9155
+ used: this.functionsScheduled,
9156
+ remaining: remaining(TRANSACTION_HEADROOM_LIMITS.functionsScheduled, this.functionsScheduled)
9157
+ },
9158
+ scheduledFunctionArgsBytes: {
9159
+ used: this.scheduledFunctionArgsBytes,
9160
+ remaining: remaining(TRANSACTION_HEADROOM_LIMITS.scheduledFunctionArgsBytes, this.scheduledFunctionArgsBytes)
9161
+ }
9162
+ };
9163
+ }
9164
+ }
9165
+
9166
+ // ../core/dist/transactor/occ-commit.js
9167
+ init_udf_trace();
9168
+
9029
9169
  // ../core/dist/transactor/occ-validation.js
9030
9170
  init_interface();
9031
9171
  init_interface();
@@ -9063,7 +9203,7 @@ function createDocumentReadValidationMap(docstore, documentReads) {
9063
9203
  if (pendingIds.length === 0) {
9064
9204
  return;
9065
9205
  }
9066
- return docstore.get_many(pendingIds);
9206
+ return docstore.getMany(pendingIds);
9067
9207
  }
9068
9208
  async function validateDocumentRead(docstore, key, readVersion, currentDocsPromise) {
9069
9209
  const parsedId = parseDocumentIdKey(key);
@@ -9120,7 +9260,7 @@ async function validateIndexRangeRead(docstore, indexId, startKey, endKey, readT
9120
9260
  const interval = { start: startKey, end: endKey };
9121
9261
  const validationReadTimestamp = resolveValidationReadTimestamp(docstore, readTimestamp);
9122
9262
  const currentDocIds = new Set;
9123
- for await (const [, doc] of docstore.index_scan(encodedIndexId, encodedTableId, validationReadTimestamp, interval, Order.Asc)) {
9263
+ for await (const [, doc] of docstore.indexScan(encodedIndexId, encodedTableId, validationReadTimestamp, interval, Order.Asc)) {
9124
9264
  currentDocIds.add(documentIdKey(doc.value.id));
9125
9265
  }
9126
9266
  for (const docId of currentDocIds) {
@@ -9159,119 +9299,47 @@ function resolveValidationReadTimestamp(docstore, minimumTimestamp) {
9159
9299
  return latestKnownTimestamp > minimumTimestamp ? latestKnownTimestamp : minimumTimestamp;
9160
9300
  }
9161
9301
 
9162
- // ../core/dist/transactor/occ-transaction.js
9302
+ // ../core/dist/transactor/occ-commit.js
9163
9303
  init_commit_lock();
9164
- init_udf_trace();
9165
-
9166
- // ../core/dist/limits/transaction-headroom.js
9167
- init_values();
9168
- var MEBIBYTE = 1024 * 1024;
9169
- var TRANSACTION_HEADROOM_LIMITS = {
9170
- bytesRead: 16 * MEBIBYTE,
9171
- bytesWritten: 16 * MEBIBYTE,
9172
- databaseQueries: 4096,
9173
- documentsRead: 32000,
9174
- documentsWritten: 16000,
9175
- functionsScheduled: 1000,
9176
- scheduledFunctionArgsBytes: 16 * MEBIBYTE
9177
- };
9178
- var encoder = new TextEncoder;
9179
- function remaining(limit, used) {
9180
- return Math.max(0, limit - used);
9181
- }
9182
- function estimateConvexValueBytes(value) {
9183
- const json = JSON.stringify(convexToJson(value));
9184
- return encoder.encode(json).byteLength;
9185
- }
9186
-
9187
- class TransactionHeadroomTracker {
9188
- bytesRead = 0;
9189
- documentsRead = 0;
9190
- databaseQueries = 0;
9191
- functionsScheduled = 0;
9192
- scheduledFunctionArgsBytes = 0;
9193
- bytesWritten = 0;
9194
- writtenDocuments = new Map;
9195
- recordDatabaseQuery(count = 1) {
9196
- this.databaseQueries += count;
9197
- }
9198
- recordRead(value) {
9199
- this.documentsRead += 1;
9200
- this.bytesRead += estimateConvexValueBytes(value);
9201
- }
9202
- recordReads(values) {
9203
- for (const value of values) {
9204
- this.recordRead(value);
9304
+ async function commitOccWrites(request) {
9305
+ let committedTimestamp = 0n;
9306
+ const runCommit = async () => {
9307
+ await withTraceSpan("occ.validate_read_set", "transaction", async () => {
9308
+ await validateReadSetForCommit(request.docstore, request.readChecks, request.writtenDocKeys);
9309
+ }, {
9310
+ readCheckCount: request.readChecks.length
9311
+ });
9312
+ committedTimestamp = await request.allocateCommitTimestamp();
9313
+ addTraceEvent("occ.commit_timestamp_allocated", {
9314
+ commitTimestamp: committedTimestamp.toString()
9315
+ });
9316
+ for (const entry of request.writeEntries) {
9317
+ entry.ts = committedTimestamp;
9205
9318
  }
9206
- }
9207
- recordScheduledFunction(args) {
9208
- this.functionsScheduled += 1;
9209
- this.scheduledFunctionArgsBytes += estimateConvexValueBytes(args);
9210
- }
9211
- trackWrittenDocument(documentKey, value) {
9212
- const nextBytes = estimateConvexValueBytes(value);
9213
- const previousBytes = this.writtenDocuments.get(documentKey);
9214
- if (previousBytes !== undefined) {
9215
- this.bytesWritten -= previousBytes;
9319
+ for (const indexEntry of request.indexEntries) {
9320
+ indexEntry.ts = committedTimestamp;
9216
9321
  }
9217
- this.writtenDocuments.set(documentKey, nextBytes);
9218
- this.bytesWritten += nextBytes;
9219
- }
9220
- snapshot() {
9221
- return {
9222
- bytesRead: this.bytesRead,
9223
- documentsRead: this.documentsRead,
9224
- databaseQueries: this.databaseQueries,
9225
- functionsScheduled: this.functionsScheduled,
9226
- scheduledFunctionArgsBytes: this.scheduledFunctionArgsBytes,
9227
- bytesWritten: this.bytesWritten,
9228
- writtenDocuments: new Map(this.writtenDocuments)
9229
- };
9230
- }
9231
- restore(snapshot) {
9232
- this.bytesRead = snapshot.bytesRead;
9233
- this.documentsRead = snapshot.documentsRead;
9234
- this.databaseQueries = snapshot.databaseQueries;
9235
- this.functionsScheduled = snapshot.functionsScheduled;
9236
- this.scheduledFunctionArgsBytes = snapshot.scheduledFunctionArgsBytes;
9237
- this.bytesWritten = snapshot.bytesWritten;
9238
- this.writtenDocuments.clear();
9239
- for (const [documentKey, bytes] of snapshot.writtenDocuments) {
9240
- this.writtenDocuments.set(documentKey, bytes);
9322
+ if (request.writeEntries.length > 0 || request.indexEntries.size > 0) {
9323
+ await withTraceSpan("occ.persist_writes", "storage", async () => {
9324
+ await request.docstore.write(request.writeEntries, request.indexEntries, "Error");
9325
+ }, {
9326
+ documentCount: request.writeEntries.length,
9327
+ indexUpdateCount: request.indexEntries.size
9328
+ });
9241
9329
  }
9330
+ };
9331
+ try {
9332
+ await commitWithDerivedSync(request.docstore, { searchstore: request.searchstore, vecstore: request.vecstore }, request.writeEntries, runCommit);
9333
+ } catch (error) {
9334
+ if (error instanceof ConflictError) {
9335
+ addTraceEvent("occ.conflict", {
9336
+ message: error.message
9337
+ });
9338
+ throw error;
9339
+ }
9340
+ throw error;
9242
9341
  }
9243
- getHeadroom() {
9244
- return {
9245
- bytesRead: {
9246
- used: this.bytesRead,
9247
- remaining: remaining(TRANSACTION_HEADROOM_LIMITS.bytesRead, this.bytesRead)
9248
- },
9249
- bytesWritten: {
9250
- used: this.bytesWritten,
9251
- remaining: remaining(TRANSACTION_HEADROOM_LIMITS.bytesWritten, this.bytesWritten)
9252
- },
9253
- databaseQueries: {
9254
- used: this.databaseQueries,
9255
- remaining: remaining(TRANSACTION_HEADROOM_LIMITS.databaseQueries, this.databaseQueries)
9256
- },
9257
- documentsRead: {
9258
- used: this.documentsRead,
9259
- remaining: remaining(TRANSACTION_HEADROOM_LIMITS.documentsRead, this.documentsRead)
9260
- },
9261
- documentsWritten: {
9262
- used: this.writtenDocuments.size,
9263
- remaining: remaining(TRANSACTION_HEADROOM_LIMITS.documentsWritten, this.writtenDocuments.size)
9264
- },
9265
- functionsScheduled: {
9266
- used: this.functionsScheduled,
9267
- remaining: remaining(TRANSACTION_HEADROOM_LIMITS.functionsScheduled, this.functionsScheduled)
9268
- },
9269
- scheduledFunctionArgsBytes: {
9270
- used: this.scheduledFunctionArgsBytes,
9271
- remaining: remaining(TRANSACTION_HEADROOM_LIMITS.scheduledFunctionArgsBytes, this.scheduledFunctionArgsBytes)
9272
- }
9273
- };
9274
- }
9342
+ return committedTimestamp;
9275
9343
  }
9276
9344
 
9277
9345
  // ../core/dist/transactor/occ-transaction.js
@@ -9426,7 +9494,7 @@ class OccMutationTransaction {
9426
9494
  const requests = Array.from(this.pendingLatestFetches.values());
9427
9495
  this.pendingLatestFetches.clear();
9428
9496
  try {
9429
- const fetched = await withTraceSpan("tx.get_many_latest", "storage", () => this.docstore.get_many(requests.map((request) => request.id), this.snapshotTimestamp), { documentCount: requests.length });
9497
+ const fetched = await withTraceSpan("tx.getManyLatest", "storage", () => this.docstore.getMany(requests.map((request) => request.id), this.snapshotTimestamp), { documentCount: requests.length });
9430
9498
  for (const request of requests) {
9431
9499
  const key = documentIdKey(request.id);
9432
9500
  const latest = fetched.get(key) ?? null;
@@ -9455,7 +9523,7 @@ class OccMutationTransaction {
9455
9523
  missingIds.push(id);
9456
9524
  }
9457
9525
  if (missingIds.length > 0) {
9458
- const fetched = await withTraceSpan("tx.get_many_latest", "storage", () => this.docstore.get_many(missingIds, this.snapshotTimestamp), { documentCount: missingIds.length });
9526
+ const fetched = await withTraceSpan("tx.getManyLatest", "storage", () => this.docstore.getMany(missingIds, this.snapshotTimestamp), { documentCount: missingIds.length });
9459
9527
  for (const id of missingIds) {
9460
9528
  const key = documentIdKey(id);
9461
9529
  const latest = fetched.get(key) ?? null;
@@ -9586,43 +9654,16 @@ class OccMutationTransaction {
9586
9654
  stagedIndexCount: indexEntries.size,
9587
9655
  readCheckCount: readChecks.length
9588
9656
  });
9589
- let committedTimestamp = 0n;
9590
- const runCommit = async () => {
9591
- await withTraceSpan("occ.validate_read_set", "transaction", async () => {
9592
- await validateReadSetForCommit(this.docstore, readChecks, writtenDocKeys);
9593
- }, {
9594
- readCheckCount: readChecks.length
9595
- });
9596
- committedTimestamp = await this.allocateCommitTimestamp();
9597
- addTraceEvent("occ.commit_timestamp_allocated", {
9598
- commitTimestamp: committedTimestamp.toString()
9599
- });
9600
- for (const entry of writeEntries) {
9601
- entry.ts = committedTimestamp;
9602
- }
9603
- for (const indexEntry of indexEntries) {
9604
- indexEntry.ts = committedTimestamp;
9605
- }
9606
- if (writeEntries.length > 0 || indexEntries.size > 0) {
9607
- await withTraceSpan("occ.persist_writes", "storage", async () => {
9608
- await this.docstore.write(writeEntries, indexEntries, "Error");
9609
- }, {
9610
- documentCount: writeEntries.length,
9611
- indexUpdateCount: indexEntries.size
9612
- });
9613
- }
9614
- };
9615
- try {
9616
- await commitWithDerivedSync(this.docstore, { searchstore: this.searchstore, vecstore: this.vecstore }, writeEntries, runCommit);
9617
- } catch (error) {
9618
- if (error instanceof ConflictError) {
9619
- addTraceEvent("occ.conflict", {
9620
- message: error.message
9621
- });
9622
- throw error;
9623
- }
9624
- throw error;
9625
- }
9657
+ const committedTimestamp = await commitOccWrites({
9658
+ docstore: this.docstore,
9659
+ searchstore: this.searchstore,
9660
+ vecstore: this.vecstore,
9661
+ writeEntries,
9662
+ indexEntries,
9663
+ readChecks,
9664
+ writtenDocKeys,
9665
+ allocateCommitTimestamp: () => this.allocateCommitTimestamp()
9666
+ });
9626
9667
  setCurrentTraceSpanAttributes({
9627
9668
  committedTimestamp: committedTimestamp.toString()
9628
9669
  });
@@ -9650,6 +9691,7 @@ class SchemaService {
9650
9691
  tableCache = new Map;
9651
9692
  schemaValidator;
9652
9693
  componentPath;
9694
+ tableRegistry;
9653
9695
  runtimeMetadataSnapshot;
9654
9696
  constructor(componentPath, tableRegistry, runtimeMetadataSnapshot) {
9655
9697
  this.componentPath = componentPath;
@@ -9860,7 +9902,7 @@ class SnapshotDocAccess {
9860
9902
  missingIds.push(id);
9861
9903
  }
9862
9904
  if (missingIds.length > 0) {
9863
- const fetched = await withTraceSpan("doc_access.get_many", "storage", () => this.docstore.get_many(missingIds, snapshotTimestamp), { documentCount: missingIds.length });
9905
+ const fetched = await withTraceSpan("doc_access.getMany", "storage", () => this.docstore.getMany(missingIds, snapshotTimestamp), { documentCount: missingIds.length });
9864
9906
  for (const id of missingIds) {
9865
9907
  const docKey = documentIdKey(id);
9866
9908
  const cacheKey = `${snapshotTimestamp}:${documentIdKey(id)}`;
@@ -9906,7 +9948,7 @@ class SnapshotDocAccess {
9906
9948
  this.pendingLatestBatches.delete(snapshotTimestamp);
9907
9949
  const requests = Array.from(batch.values());
9908
9950
  try {
9909
- const results = await withTraceSpan("doc_access.get_many", "storage", () => this.docstore.get_many(requests.map((request) => request.id), snapshotTimestamp), { documentCount: requests.length });
9951
+ const results = await withTraceSpan("doc_access.getMany", "storage", () => this.docstore.getMany(requests.map((request) => request.id), snapshotTimestamp), { documentCount: requests.length });
9910
9952
  for (const request of requests) {
9911
9953
  request.resolve(results.get(documentIdKey(request.id)) ?? null);
9912
9954
  }
@@ -9927,7 +9969,7 @@ class SnapshotDocAccess {
9927
9969
  hasTransaction() {
9928
9970
  return false;
9929
9971
  }
9930
- getDocStore() {
9972
+ getIndexReader() {
9931
9973
  return this.docstore;
9932
9974
  }
9933
9975
  getWriteVersion() {
@@ -9983,7 +10025,7 @@ class TransactionalDocAccess {
9983
10025
  hasTransaction() {
9984
10026
  return true;
9985
10027
  }
9986
- getDocStore() {
10028
+ getIndexReader() {
9987
10029
  return this.docstore;
9988
10030
  }
9989
10031
  getWriteVersion() {
@@ -10174,7 +10216,7 @@ function rangeExpressionsToIndexBounds(expressions, indexFields) {
10174
10216
  }
10175
10217
  return { start, end };
10176
10218
  }
10177
- async function executeIndexQuery(docstore, tableName, indexName, indexFields, expressions, order, limit, cursor, snapshotTimestamp, onDocumentRead, options) {
10219
+ async function executeIndexQuery(indexReader, tableName, indexName, indexFields, expressions, order, limit, cursor, snapshotTimestamp, onDocumentRead, options) {
10178
10220
  return withTraceSpan("query.index.scan", "storage", async () => {
10179
10221
  const tableId = stringToHex(tableName);
10180
10222
  const indexId = stringToHex(`${tableName}:${indexName}`);
@@ -10196,8 +10238,8 @@ async function executeIndexQuery(docstore, tableName, indexName, indexFields, ex
10196
10238
  }
10197
10239
  const results = [];
10198
10240
  const scanLimit = limit !== null ? limit + 1 : Number.MAX_SAFE_INTEGER;
10199
- const bulkDocStore = docstore;
10200
- const canUseResumePushdown = resumeIndexKey !== null && typeof bulkDocStore.index_scan_rows_after_key === "function";
10241
+ const bulkIndexReader = indexReader;
10242
+ const canUseResumePushdown = resumeIndexKey !== null && typeof bulkIndexReader.indexScanRowsAfterKey === "function";
10201
10243
  const skippingNeedsInMemoryPass = cursor !== null;
10202
10244
  const pushdownLimit = limit !== null && !skippingNeedsInMemoryPass ? scanLimit : undefined;
10203
10245
  let count = 0;
@@ -10235,21 +10277,21 @@ async function executeIndexQuery(docstore, tableName, indexName, indexFields, ex
10235
10277
  addTraceEvent("query.index.scan.pushdown_resume", {
10236
10278
  resumeMode: "index_key"
10237
10279
  });
10238
- const rows = await bulkDocStore.index_scan_rows_after_key(indexId, tableId, readTimestamp, interval, indexOrder, resumeIndexKey, pushdownLimit);
10280
+ const rows = await bulkIndexReader.indexScanRowsAfterKey(indexId, tableId, readTimestamp, interval, indexOrder, resumeIndexKey, pushdownLimit);
10239
10281
  for (const [indexKey, document] of rows) {
10240
10282
  if (!processRow(indexKey, document)) {
10241
10283
  break;
10242
10284
  }
10243
10285
  }
10244
- } else if (typeof bulkDocStore.index_scan_rows === "function") {
10245
- const rows = await bulkDocStore.index_scan_rows(indexId, tableId, readTimestamp, interval, indexOrder, pushdownLimit);
10286
+ } else if (typeof bulkIndexReader.indexScanRows === "function") {
10287
+ const rows = await bulkIndexReader.indexScanRows(indexId, tableId, readTimestamp, interval, indexOrder, pushdownLimit);
10246
10288
  for (const [indexKey, document] of rows) {
10247
10289
  if (!processRow(indexKey, document)) {
10248
10290
  break;
10249
10291
  }
10250
10292
  }
10251
10293
  } else {
10252
- const generator = docstore.index_scan(indexId, tableId, readTimestamp, interval, indexOrder, pushdownLimit);
10294
+ const generator = indexReader.indexScan(indexId, tableId, readTimestamp, interval, indexOrder, pushdownLimit);
10253
10295
  for await (const [indexKey, document] of generator) {
10254
10296
  if (!processRow(indexKey, document)) {
10255
10297
  break;
@@ -10951,7 +10993,7 @@ async function executeIndexRangePlan(plan, cursor, limit, deps) {
10951
10993
  let paginationResult;
10952
10994
  let usedFallback = false;
10953
10995
  try {
10954
- const indexResult = await executeIndexQuery(deps.docStore.getDocStore(), plan.fullTableName, plan.indexDescriptor, plan.indexFields, plan.expressions, plan.order, limit, cursor, deps.context.snapshotTimestamp, observedDocuments ? (latestDoc) => {
10996
+ const indexResult = await executeIndexQuery(deps.docStore.getIndexReader(), plan.fullTableName, plan.indexDescriptor, plan.indexFields, plan.expressions, plan.order, limit, cursor, deps.context.snapshotTimestamp, observedDocuments ? (latestDoc) => {
10955
10997
  observedDocuments.set(documentIdKey(latestDoc.value.id), latestDoc);
10956
10998
  } : undefined, {
10957
10999
  bounds: { start, end }
@@ -12083,19 +12125,30 @@ function getSyscallApiProfile(id = "convex-1.0") {
12083
12125
  }
12084
12126
 
12085
12127
  // ../core/dist/kernel/syscalls/capabilities.js
12086
- var CAPABILITY_UDF_TYPES = {
12087
- databaseRead: ["query", "mutation"],
12088
- databaseWrite: ["mutation"],
12089
- nestedQuery: ["query", "mutation", "action", "httpAction"],
12090
- nestedMutation: ["mutation", "action", "httpAction"],
12091
- nestedAction: ["action", "httpAction"],
12092
- actionSearch: ["action", "httpAction"],
12093
- functionHandle: ["query", "mutation", "action", "httpAction"],
12094
- mutationScheduler: ["mutation"],
12095
- actionScheduler: ["action", "httpAction"]
12128
+ var UDF_SYSCALL_CAPABILITIES = {
12129
+ query: ["databaseRead", "nestedQuery", "functionHandle", "transactionHeadroom"],
12130
+ mutation: [
12131
+ "databaseRead",
12132
+ "databaseWrite",
12133
+ "nestedQuery",
12134
+ "nestedMutation",
12135
+ "functionHandle",
12136
+ "mutationScheduler",
12137
+ "transactionHeadroom"
12138
+ ],
12139
+ action: ["nestedQuery", "nestedMutation", "nestedAction", "actionSearch", "functionHandle", "actionScheduler"],
12140
+ httpAction: ["nestedQuery", "nestedMutation", "nestedAction", "actionSearch", "functionHandle", "actionScheduler"]
12096
12141
  };
12142
+ var NESTED_UDF_CAPABILITY = {
12143
+ query: "nestedQuery",
12144
+ mutation: "nestedMutation",
12145
+ action: "nestedAction"
12146
+ };
12147
+ function hasSyscallCapability(udfType, capability) {
12148
+ return UDF_SYSCALL_CAPABILITIES[udfType].includes(capability);
12149
+ }
12097
12150
  function assertSyscallCapability(udfType, capability, operation) {
12098
- if (CAPABILITY_UDF_TYPES[capability].includes(udfType)) {
12151
+ if (hasSyscallCapability(udfType, capability)) {
12099
12152
  return;
12100
12153
  }
12101
12154
  throw new Error(`${operation} not available in ${formatUdfType(udfType)}`);
@@ -12114,6 +12167,12 @@ function formatUdfType(udfType) {
12114
12167
  }
12115
12168
 
12116
12169
  // ../core/dist/kernel/syscalls/action-syscalls.js
12170
+ var NESTED_UDF_OPERATION = {
12171
+ query: "Nested queries",
12172
+ mutation: "Nested mutations",
12173
+ action: "Nested actions"
12174
+ };
12175
+
12117
12176
  class ActionSyscalls {
12118
12177
  context;
12119
12178
  queryRuntime;
@@ -12139,7 +12198,7 @@ class ActionSyscalls {
12139
12198
  router.registerAsync(this.ops.createFunctionHandle, (args) => this.handleCreateFunctionHandle(args));
12140
12199
  }
12141
12200
  async handleActionQuery(args) {
12142
- this.requireNestedQuery();
12201
+ this.requireNestedCall("query");
12143
12202
  const target = resolveFunctionTarget(args, this.context.componentPath);
12144
12203
  const udfArguments = normalizeUdfArgsPayload(args.args);
12145
12204
  return await this.invocationManager.execute(target.udfPath, udfArguments, "query", target.componentPath);
@@ -12173,15 +12232,8 @@ class ActionSyscalls {
12173
12232
  assertSyscallCapability(this.context.udfType, "actionSearch", "Search");
12174
12233
  return this.queryRuntime.runSearchAction(args.query);
12175
12234
  }
12176
- requireNestedQuery() {
12177
- assertSyscallCapability(this.context.udfType, "nestedQuery", "Nested queries");
12178
- }
12179
12235
  requireNestedCall(type) {
12180
- if (type === "query") {
12181
- this.requireNestedQuery();
12182
- return;
12183
- }
12184
- assertSyscallCapability(this.context.udfType, type === "mutation" ? "nestedMutation" : "nestedAction", type === "mutation" ? "Nested mutations" : "Nested actions");
12236
+ assertSyscallCapability(this.context.udfType, NESTED_UDF_CAPABILITY[type], NESTED_UDF_OPERATION[type]);
12185
12237
  }
12186
12238
  }
12187
12239
 
@@ -12517,7 +12569,7 @@ class HeadroomSyscalls {
12517
12569
  router.registerAsync(this.ops.headroom, async () => this.handleHeadroom());
12518
12570
  }
12519
12571
  handleHeadroom() {
12520
- if (this.context.udfType !== "query" && this.context.udfType !== "mutation") {
12572
+ if (!hasSyscallCapability(this.context.udfType, "transactionHeadroom")) {
12521
12573
  throw new Error(`Unknown async operation: ${this.ops.headroom}`);
12522
12574
  }
12523
12575
  return this.context.getTransactionHeadroom();
@@ -12538,14 +12590,14 @@ class IdentitySyscalls {
12538
12590
  }
12539
12591
  handleGetUserIdentity() {
12540
12592
  this.context.markAuthAccessed();
12541
- const authContext2 = this.context.authContext;
12542
- if (!authContext2) {
12593
+ const authContext = this.context.authContext;
12594
+ if (!authContext) {
12543
12595
  return null;
12544
12596
  }
12545
- if (authContext2.userIdentity) {
12546
- return authContext2.userIdentity;
12597
+ if (authContext.userIdentity) {
12598
+ return authContext.userIdentity;
12547
12599
  }
12548
- const token = authContext2.token;
12600
+ const token = authContext.token;
12549
12601
  if (!token) {
12550
12602
  return null;
12551
12603
  }
@@ -12584,14 +12636,16 @@ class JsSyscallRouter {
12584
12636
 
12585
12637
  // ../core/dist/kernel/syscalls/query-syscalls.js
12586
12638
  class QuerySyscalls {
12587
- queryRuntime;
12588
12639
  nextQueryId = 1;
12589
12640
  queryResults = {};
12590
12641
  pendingQueries = {};
12642
+ context;
12643
+ queryRuntime;
12591
12644
  ops;
12592
- constructor(queryRuntime, ops = CONVEX_1_0_SYSCALL_API.query) {
12593
- this.queryRuntime = queryRuntime;
12594
- this.ops = ops;
12645
+ constructor(options) {
12646
+ this.context = options.context;
12647
+ this.queryRuntime = options.queryRuntime;
12648
+ this.ops = options.ops ?? CONVEX_1_0_SYSCALL_API.query;
12595
12649
  }
12596
12650
  register(router) {
12597
12651
  router.registerSync(this.ops.queryStream, (args) => this.handleQueryStream(args));
@@ -12600,18 +12654,21 @@ class QuerySyscalls {
12600
12654
  router.registerAsync(this.ops.queryPage, (args) => this.handleQueryPage(args));
12601
12655
  }
12602
12656
  handleQueryStream(args) {
12657
+ this.requireDatabaseRead();
12603
12658
  const { query } = args;
12604
12659
  const queryId = this.nextQueryId++;
12605
12660
  this.pendingQueries[queryId] = query;
12606
12661
  return { queryId };
12607
12662
  }
12608
12663
  handleQueryCleanup(args) {
12664
+ this.requireDatabaseRead();
12609
12665
  const queryId = args.queryId;
12610
12666
  delete this.pendingQueries[queryId];
12611
12667
  delete this.queryResults[queryId];
12612
12668
  return {};
12613
12669
  }
12614
12670
  async handleQueryStreamNext(args) {
12671
+ this.requireDatabaseRead();
12615
12672
  const queryId = args.queryId;
12616
12673
  if (this.pendingQueries[queryId]) {
12617
12674
  const query = this.pendingQueries[queryId];
@@ -12631,6 +12688,7 @@ class QuerySyscalls {
12631
12688
  return { value, done: false };
12632
12689
  }
12633
12690
  async handleQueryPage(args) {
12691
+ this.requireDatabaseRead();
12634
12692
  const { query, cursor, pageSize } = args;
12635
12693
  if (cursor === "_end_cursor") {
12636
12694
  return {
@@ -12646,6 +12704,9 @@ class QuerySyscalls {
12646
12704
  continueCursor: paginatedResult.hasMore ? paginatedResult.nextCursor : "_end_cursor"
12647
12705
  };
12648
12706
  }
12707
+ requireDatabaseRead() {
12708
+ assertSyscallCapability(this.context.udfType, "databaseRead", "Database reads");
12709
+ }
12649
12710
  }
12650
12711
 
12651
12712
  // ../core/dist/kernel/syscalls/schedule-syscalls.js
@@ -12659,15 +12720,17 @@ class ScheduleSyscalls {
12659
12720
  this.ops = options.ops ?? CONVEX_1_0_SYSCALL_API.schedule;
12660
12721
  }
12661
12722
  register(router) {
12662
- router.registerAsync(this.ops.schedule, (args) => this.handleSchedule(args, false), { argsFormat: "convex" });
12663
- router.registerAsync(this.ops.scheduleFromAction, (args) => this.handleSchedule(args, true), {
12723
+ router.registerAsync(this.ops.schedule, (args) => this.handleSchedule(args, "mutationScheduler"), {
12664
12724
  argsFormat: "convex"
12665
12725
  });
12666
- router.registerAsync(this.ops.cancelJobFromAction, (args) => this.handleCancelJob(args, true));
12667
- router.registerAsync(this.ops.cancelJob, (args) => this.handleCancelJob(args, false));
12726
+ router.registerAsync(this.ops.scheduleFromAction, (args) => this.handleSchedule(args, "actionScheduler"), {
12727
+ argsFormat: "convex"
12728
+ });
12729
+ router.registerAsync(this.ops.cancelJobFromAction, (args) => this.handleCancelJob(args, "actionScheduler"));
12730
+ router.registerAsync(this.ops.cancelJob, (args) => this.handleCancelJob(args, "mutationScheduler"));
12668
12731
  }
12669
- async handleSchedule(args, isAction) {
12670
- this.requireScheduler(isAction);
12732
+ async handleSchedule(args, capability) {
12733
+ this.requireScheduler(capability);
12671
12734
  const target = resolveFunctionTarget(args, this.context.componentPath);
12672
12735
  const { args: fnArgs, ts } = args;
12673
12736
  if (fnArgs === undefined || typeof ts !== "number") {
@@ -12676,8 +12739,8 @@ class ScheduleSyscalls {
12676
12739
  const componentPathForJob = normalizeComponentPathValue(target.componentPath ?? this.context.componentPath);
12677
12740
  return this.scheduler.schedule(target.udfPath, fnArgs, ts, componentPathForJob);
12678
12741
  }
12679
- async handleCancelJob(args, isAction) {
12680
- this.requireScheduler(isAction);
12742
+ async handleCancelJob(args, capability) {
12743
+ this.requireScheduler(capability);
12681
12744
  const { id, state } = args;
12682
12745
  if (typeof id !== "string") {
12683
12746
  throw new Error("`id` argument for `cancel_job` must be a string.");
@@ -12685,8 +12748,8 @@ class ScheduleSyscalls {
12685
12748
  await this.scheduler.cancel(id, state);
12686
12749
  return {};
12687
12750
  }
12688
- requireScheduler(isAction) {
12689
- assertSyscallCapability(this.context.udfType, isAction ? "actionScheduler" : "mutationScheduler", "Scheduler");
12751
+ requireScheduler(capability) {
12752
+ assertSyscallCapability(this.context.udfType, capability, "Scheduler");
12690
12753
  }
12691
12754
  }
12692
12755
 
@@ -12828,7 +12891,11 @@ class KernelSyscalls {
12828
12891
  context: resources.context,
12829
12892
  udfExecutor: resources.udfExecutor
12830
12893
  });
12831
- new QuerySyscalls(resources.queryRuntime, syscallApi.query).register(this.router);
12894
+ new QuerySyscalls({
12895
+ context: resources.context,
12896
+ queryRuntime: resources.queryRuntime,
12897
+ ops: syscallApi.query
12898
+ }).register(this.router);
12832
12899
  new DatabaseSyscalls({
12833
12900
  context: resources.context,
12834
12901
  docStore: resources.docStore,
@@ -13558,6 +13625,16 @@ function rangesToTables(ranges) {
13558
13625
  }
13559
13626
  return tables;
13560
13627
  }
13628
+ function cloneSetMap(source) {
13629
+ const clone = new Map;
13630
+ copySetMap(source, clone);
13631
+ return clone;
13632
+ }
13633
+ function copySetMap(source, target) {
13634
+ for (const [key, values] of source) {
13635
+ target.set(key, new Set(values));
13636
+ }
13637
+ }
13561
13638
  var TABLE_WRITE_TIMESTAMP_TTL_MS = 60 * 60 * 1000;
13562
13639
  var RECENT_WRITE_RANGE_TTL_MS = 60 * 1000;
13563
13640
  var TABLE_WRITE_TIMESTAMP_MAX_SIZE = 1e4;
@@ -13571,6 +13648,30 @@ class SubscriptionGraph {
13571
13648
  clientQueryToId = new Map;
13572
13649
  hashToTables = new Map;
13573
13650
  tableToHashes = new Map;
13651
+ apply(change) {
13652
+ const snapshot = this.snapshot();
13653
+ try {
13654
+ switch (change.type) {
13655
+ case "subscribe":
13656
+ this.setClientQueryHash(change.clientQuery, change.queryId, change.queryHash);
13657
+ this.setQueryTables(change.queryHash, change.tables);
13658
+ break;
13659
+ case "unsubscribe":
13660
+ this.removeClientQuery(change.clientQuery);
13661
+ break;
13662
+ case "unsubscribeClient":
13663
+ this.removeClient(change.clientId);
13664
+ break;
13665
+ case "renameClient":
13666
+ this.renameClient(change.oldClientId, change.newClientId);
13667
+ break;
13668
+ }
13669
+ this.assertConsistent();
13670
+ } catch (error) {
13671
+ this.restore(snapshot);
13672
+ throw error;
13673
+ }
13674
+ }
13574
13675
  getClientQueriesForHash(hash) {
13575
13676
  return this.hashToClientQueries.get(hash) ?? new Set;
13576
13677
  }
@@ -13623,6 +13724,11 @@ class SubscriptionGraph {
13623
13724
  const hash = this.clientQueryToHash.get(oldKey);
13624
13725
  if (!hash)
13625
13726
  return;
13727
+ if (oldKey === newKey) {
13728
+ this.clientQueryToId.set(oldKey, newQueryId);
13729
+ return;
13730
+ }
13731
+ this.removeClientQuery(newKey);
13626
13732
  this.clientQueryToHash.delete(oldKey);
13627
13733
  this.clientQueryToId.delete(oldKey);
13628
13734
  this.clientQueryToHash.set(newKey, hash);
@@ -13631,6 +13737,54 @@ class SubscriptionGraph {
13631
13737
  cqSet.delete(oldKey);
13632
13738
  cqSet.add(newKey);
13633
13739
  }
13740
+ assertConsistent() {
13741
+ for (const [hash, clientQueries] of this.hashToClientQueries) {
13742
+ if (clientQueries.size === 0) {
13743
+ throw new Error(`SubscriptionGraph invariant failed: empty client query set for ${hash}`);
13744
+ }
13745
+ for (const clientQuery of clientQueries) {
13746
+ if (this.clientQueryToHash.get(clientQuery) !== hash) {
13747
+ throw new Error(`SubscriptionGraph invariant failed: stale client query ${clientQuery} for ${hash}`);
13748
+ }
13749
+ if (!this.clientQueryToId.has(clientQuery)) {
13750
+ throw new Error(`SubscriptionGraph invariant failed: missing query id for ${clientQuery}`);
13751
+ }
13752
+ }
13753
+ }
13754
+ for (const [clientQuery, hash] of this.clientQueryToHash) {
13755
+ if (!this.hashToClientQueries.get(hash)?.has(clientQuery)) {
13756
+ throw new Error(`SubscriptionGraph invariant failed: missing reverse hash entry for ${clientQuery}`);
13757
+ }
13758
+ if (!this.clientQueryToId.has(clientQuery)) {
13759
+ throw new Error(`SubscriptionGraph invariant failed: missing query id for ${clientQuery}`);
13760
+ }
13761
+ }
13762
+ for (const clientQuery of this.clientQueryToId.keys()) {
13763
+ if (!this.clientQueryToHash.has(clientQuery)) {
13764
+ throw new Error(`SubscriptionGraph invariant failed: orphaned query id for ${clientQuery}`);
13765
+ }
13766
+ }
13767
+ for (const [hash, tables] of this.hashToTables) {
13768
+ if (!this.hashToClientQueries.has(hash)) {
13769
+ throw new Error(`SubscriptionGraph invariant failed: table dependencies for orphaned hash ${hash}`);
13770
+ }
13771
+ for (const table of tables) {
13772
+ if (!this.tableToHashes.get(table)?.has(hash)) {
13773
+ throw new Error(`SubscriptionGraph invariant failed: missing reverse table entry for ${hash} on ${table}`);
13774
+ }
13775
+ }
13776
+ }
13777
+ for (const [table, hashes] of this.tableToHashes) {
13778
+ if (hashes.size === 0) {
13779
+ throw new Error(`SubscriptionGraph invariant failed: empty hash set for table ${table}`);
13780
+ }
13781
+ for (const hash of hashes) {
13782
+ if (!this.hashToTables.get(hash)?.has(table)) {
13783
+ throw new Error(`SubscriptionGraph invariant failed: stale table hash ${hash} for ${table}`);
13784
+ }
13785
+ }
13786
+ }
13787
+ }
13634
13788
  setQueryTables(hash, tables) {
13635
13789
  if (!this.hashToClientQueries.has(hash))
13636
13790
  return;
@@ -13686,6 +13840,56 @@ class SubscriptionGraph {
13686
13840
  *hashes() {
13687
13841
  yield* this.hashToClientQueries.keys();
13688
13842
  }
13843
+ removeClient(clientId) {
13844
+ const prefix = `${clientId}:`;
13845
+ const keysToRemove = [];
13846
+ for (const [key] of this.clientQueryToHash) {
13847
+ if (key.startsWith(prefix)) {
13848
+ keysToRemove.push(key);
13849
+ }
13850
+ }
13851
+ for (const key of keysToRemove) {
13852
+ this.removeClientQuery(key);
13853
+ }
13854
+ }
13855
+ renameClient(oldClientId, newClientId) {
13856
+ const prefix = `${oldClientId}:`;
13857
+ const updates = [];
13858
+ for (const [key] of this.clientQueryToHash) {
13859
+ if (key.startsWith(prefix)) {
13860
+ const queryId = this.clientQueryToId.get(key);
13861
+ if (queryId !== undefined) {
13862
+ updates.push({ oldKey: key, newKey: makeClientQueryKey(newClientId, queryId), queryId });
13863
+ }
13864
+ }
13865
+ }
13866
+ for (const { oldKey, newKey, queryId } of updates) {
13867
+ this.renameClientQuery(oldKey, newKey, queryId);
13868
+ }
13869
+ }
13870
+ snapshot() {
13871
+ return {
13872
+ hashToClientQueries: cloneSetMap(this.hashToClientQueries),
13873
+ clientQueryToHash: new Map(this.clientQueryToHash),
13874
+ clientQueryToId: new Map(this.clientQueryToId),
13875
+ hashToTables: cloneSetMap(this.hashToTables),
13876
+ tableToHashes: cloneSetMap(this.tableToHashes)
13877
+ };
13878
+ }
13879
+ restore(snapshot) {
13880
+ this.hashToClientQueries.clear();
13881
+ this.clientQueryToHash.clear();
13882
+ this.clientQueryToId.clear();
13883
+ this.hashToTables.clear();
13884
+ this.tableToHashes.clear();
13885
+ copySetMap(snapshot.hashToClientQueries, this.hashToClientQueries);
13886
+ for (const [key, value] of snapshot.clientQueryToHash)
13887
+ this.clientQueryToHash.set(key, value);
13888
+ for (const [key, value] of snapshot.clientQueryToId)
13889
+ this.clientQueryToId.set(key, value);
13890
+ copySetMap(snapshot.hashToTables, this.hashToTables);
13891
+ copySetMap(snapshot.tableToHashes, this.tableToHashes);
13892
+ }
13689
13893
  }
13690
13894
 
13691
13895
  class SubscriptionManager {
@@ -13696,9 +13900,14 @@ class SubscriptionManager {
13696
13900
  subscribe(clientId, queryId, dependencies, queryHash, snapshotTimestamp) {
13697
13901
  const hash = queryHash ?? makeClientQueryKey(clientId, queryId);
13698
13902
  const clientQueryKey = makeClientQueryKey(clientId, queryId);
13699
- this.graph.setClientQueryHash(clientQueryKey, queryId, hash);
13700
13903
  const tables = rangesToTables(dependencies.ranges);
13701
- this.graph.setQueryTables(hash, tables);
13904
+ this.graph.apply({
13905
+ type: "subscribe",
13906
+ clientQuery: clientQueryKey,
13907
+ queryId,
13908
+ queryHash: hash,
13909
+ tables
13910
+ });
13702
13911
  let needsRerun = false;
13703
13912
  const now = Date.now();
13704
13913
  const preciseCheckedTables = new Set;
@@ -13741,18 +13950,10 @@ class SubscriptionManager {
13741
13950
  }
13742
13951
  unsubscribe(clientId, queryId) {
13743
13952
  const clientQueryKey = makeClientQueryKey(clientId, queryId);
13744
- this.graph.removeClientQuery(clientQueryKey);
13953
+ this.graph.apply({ type: "unsubscribe", clientQuery: clientQueryKey });
13745
13954
  }
13746
13955
  unsubscribeAll(clientId) {
13747
- const keysToRemove = [];
13748
- for (const [key] of this.graph.clientQueries()) {
13749
- if (key.startsWith(`${clientId}:`)) {
13750
- keysToRemove.push(key);
13751
- }
13752
- }
13753
- for (const key of keysToRemove) {
13754
- this.graph.removeClientQuery(key);
13755
- }
13956
+ this.graph.apply({ type: "unsubscribeClient", clientId });
13756
13957
  }
13757
13958
  findAffectedQueries(writtenRanges) {
13758
13959
  const writtenTables = rangesToTables(writtenRanges);
@@ -13863,18 +14064,7 @@ class SubscriptionManager {
13863
14064
  return queries;
13864
14065
  }
13865
14066
  updateSessionId(oldClientId, newClientId) {
13866
- const updates = [];
13867
- for (const [key] of this.graph.clientQueries()) {
13868
- if (key.startsWith(`${oldClientId}:`)) {
13869
- const queryId = this.graph.getOriginalQueryId(key);
13870
- if (queryId !== undefined) {
13871
- updates.push({ oldKey: key, newKey: makeClientQueryKey(newClientId, queryId), queryId });
13872
- }
13873
- }
13874
- }
13875
- for (const { oldKey, newKey, queryId } of updates) {
13876
- this.graph.renameClientQuery(oldKey, newKey, queryId);
13877
- }
14067
+ this.graph.apply({ type: "renameClient", oldClientId, newClientId });
13878
14068
  }
13879
14069
  getStats() {
13880
14070
  const clients = new Set;
@@ -13889,7 +14079,9 @@ class SubscriptionManager {
13889
14079
  totalTrackedWriteTimestamps: this.tableWriteTimestamps.size
13890
14080
  };
13891
14081
  }
13892
- assertConsistency() {}
14082
+ assertConsistency() {
14083
+ this.graph.assertConsistent();
14084
+ }
13893
14085
  forceCleanupTableWriteTimestamps() {
13894
14086
  const sizeBefore = this.tableWriteTimestamps.size;
13895
14087
  this.lastCleanupTime = 0;
@@ -14339,13 +14531,13 @@ var udfMathRandom2 = () => {
14339
14531
  const udfRuntime = UDF_ASYNC_CONTEXT.getStore();
14340
14532
  return (udfRuntime?.mathRandom ?? OG_MATH_RANDOM)();
14341
14533
  };
14342
- var udfSetInterval = (callback, delay) => {
14534
+ var udfSetInterval = (callback, delay, ...args) => {
14343
14535
  const udfRuntime = UDF_ASYNC_CONTEXT.getStore();
14344
- return (udfRuntime?.setInterval ?? OG_SET_INTERVAL)(callback, delay ?? 0);
14536
+ return (udfRuntime?.setInterval ?? OG_SET_INTERVAL)(callback, delay ?? 0, ...args);
14345
14537
  };
14346
- var udfSetTimeout = (callback, delay) => {
14538
+ var udfSetTimeout = (callback, delay, ...args) => {
14347
14539
  const udfRuntime = UDF_ASYNC_CONTEXT.getStore();
14348
- return (udfRuntime?.setTimeout ?? OG_SET_TIMEOUT)(callback, delay ?? 0);
14540
+ return (udfRuntime?.setTimeout ?? OG_SET_TIMEOUT)(callback, delay ?? 0, ...args);
14349
14541
  };
14350
14542
  var udfCryptoRandomUUID2 = () => {
14351
14543
  const udfRuntime = UDF_ASYNC_CONTEXT.getStore();
@@ -14419,15 +14611,19 @@ function resolveSeed(kind, requestId, tnow) {
14419
14611
  fallbackSeedCounter += 1;
14420
14612
  return `udf:${kind}:${tnow}:${fallbackSeedCounter}:${OG_CRYPTO_RANDOM_UUID()}`;
14421
14613
  }
14614
+ function isKernelAuthContext(auth) {
14615
+ return !!auth && typeof auth === "object" && "tokenType" in auth && (auth.tokenType === "Admin" || auth.tokenType === "System" || auth.tokenType === "User" || auth.tokenType === "None");
14616
+ }
14422
14617
  function resolveEffectiveKernelAuth(auth) {
14423
14618
  const ambientIdentity = getAuthContext();
14424
- if (auth && typeof auth === "object" && "tokenType" in auth) {
14619
+ if (isKernelAuthContext(auth)) {
14425
14620
  return {
14426
14621
  ...auth,
14427
14622
  userIdentity: auth.userIdentity ?? ambientIdentity
14428
14623
  };
14429
14624
  }
14430
- return ambientIdentity ?? auth;
14625
+ const userIdentity = ambientIdentity ?? auth;
14626
+ return userIdentity ? { tokenType: "User", userIdentity } : undefined;
14431
14627
  }
14432
14628
  function resolveExecutionIdGenerator(deterministicSeed, explicitIdGenerator) {
14433
14629
  if (explicitIdGenerator) {
@@ -14436,20 +14632,12 @@ function resolveExecutionIdGenerator(deterministicSeed, explicitIdGenerator) {
14436
14632
  return idGeneratorContext.getStore() ?? (deterministicSeed ? createDeterministicIdGenerator(deterministicSeed) : undefined);
14437
14633
  }
14438
14634
  function createExecutionKernel(options) {
14439
- const capabilities = {};
14440
- if (options.storage) {
14441
- capabilities.blobs = { store: options.storage, consistency: "eventual" };
14442
- }
14443
- if (options.searchstore) {
14444
- capabilities.search = options.searchstore;
14445
- }
14446
- if (options.vecstore) {
14447
- capabilities.vector = options.vecstore;
14448
- }
14449
14635
  const convex = buildKernel({
14450
14636
  services: {
14451
14637
  docstore: options.docstore,
14452
- capabilities,
14638
+ ...options.storage ? { blobstore: options.storage } : {},
14639
+ ...options.searchstore ? { searchstore: options.searchstore } : {},
14640
+ ...options.vecstore ? { vecstore: options.vecstore } : {},
14453
14641
  udfExecutor: options.udfExecutor
14454
14642
  },
14455
14643
  authContext: resolveEffectiveKernelAuth(options.auth),
@@ -14720,6 +14908,82 @@ async function runUdfHttpAction(docstore, fn, auth, storage2, searchstore2, vecs
14720
14908
 
14721
14909
  // ../core/dist/udf/executor/inline.js
14722
14910
  init_module_loader();
14911
+
14912
+ // ../core/dist/udf/function-resolution.js
14913
+ function normalizeUdfFunctionTarget(input, options = {}) {
14914
+ const policy = options.policy ?? {};
14915
+ if (input.startsWith("function://")) {
14916
+ if (policy.allowFunctionHandle === false) {
14917
+ throw new Error(`Invalid UDF path: ${input}`);
14918
+ }
14919
+ const remainder = input.slice("function://".length);
14920
+ const separatorIndex = remainder.indexOf(";");
14921
+ if (separatorIndex === -1) {
14922
+ throw new Error(`Invalid function handle: ${input}`);
14923
+ }
14924
+ const componentPath = normalizeComponentPath2(remainder.slice(0, separatorIndex));
14925
+ const udfPath = remainder.slice(separatorIndex + 1);
14926
+ const target = normalizePlainUdfPath(udfPath, {
14927
+ componentPath: componentPath ?? options.componentPath,
14928
+ policy
14929
+ });
14930
+ return {
14931
+ ...target,
14932
+ componentPath: componentPath ?? target.componentPath,
14933
+ isFunctionHandle: true
14934
+ };
14935
+ }
14936
+ return normalizePlainUdfPath(input, options);
14937
+ }
14938
+ function classifyUdfFunction(fn) {
14939
+ if (fn === null || typeof fn !== "object" && typeof fn !== "function") {
14940
+ return null;
14941
+ }
14942
+ const types = [];
14943
+ if (fn.isQuery)
14944
+ types.push("query");
14945
+ if (fn.isMutation)
14946
+ types.push("mutation");
14947
+ if (fn.isAction)
14948
+ types.push("action");
14949
+ return types.length === 1 ? types[0] : null;
14950
+ }
14951
+ function normalizePlainUdfPath(input, options = {}) {
14952
+ const policy = options.policy ?? {};
14953
+ let path = input;
14954
+ if (policy.allowSlashPath && !path.includes(":") && path.includes("/")) {
14955
+ const lastSlash = path.lastIndexOf("/");
14956
+ path = path.substring(0, lastSlash) + ":" + path.substring(lastSlash + 1);
14957
+ }
14958
+ const parts = path.split(":");
14959
+ if (parts.length === 2 && parts[0].length > 0 && parts[1].length > 0) {
14960
+ return {
14961
+ path,
14962
+ modulePath: parts[0],
14963
+ exportName: parts[1],
14964
+ componentPath: normalizeComponentPath2(options.componentPath),
14965
+ isFunctionHandle: false
14966
+ };
14967
+ }
14968
+ if (parts.length === 1 && policy.allowDefaultExport && parts[0].length > 0) {
14969
+ return {
14970
+ path: `${parts[0]}:default`,
14971
+ modulePath: parts[0],
14972
+ exportName: "default",
14973
+ componentPath: normalizeComponentPath2(options.componentPath),
14974
+ isFunctionHandle: false
14975
+ };
14976
+ }
14977
+ throw new Error(`Invalid UDF path: ${input}`);
14978
+ }
14979
+ function normalizeComponentPath2(componentPath) {
14980
+ if (!componentPath) {
14981
+ return;
14982
+ }
14983
+ return componentPath.length > 0 ? componentPath : undefined;
14984
+ }
14985
+
14986
+ // ../core/dist/udf/executor/inline.js
14723
14987
  init_validator2();
14724
14988
 
14725
14989
  // ../core/dist/errors/index.js
@@ -14889,22 +15153,8 @@ class InlineUdfExecutor {
14889
15153
  this.bootstrapState = options.bootstrapState ?? new InlineExecutorBootstrapState;
14890
15154
  }
14891
15155
  withAmbientAuth(auth, fn) {
14892
- let authContext2;
14893
- let userIdentity;
14894
- if (auth && typeof auth === "object" && "tokenType" in auth) {
14895
- authContext2 = auth;
14896
- userIdentity = authContext2.tokenType === "User" && !authContext2.userIdentity && authContext2.token ? identityFromTrustedToken(authContext2.token) : authContext2.userIdentity;
14897
- if (userIdentity && authContext2.tokenType === "User") {
14898
- authContext2 = {
14899
- ...authContext2,
14900
- userIdentity
14901
- };
14902
- }
14903
- } else {
14904
- userIdentity = auth;
14905
- }
14906
- const principal2 = authContext2 ? legacyAuthContextToPrincipal(authContext2) : userIdentity ? legacyAuthContextToPrincipal({ tokenType: "User", userIdentity }) : legacyAuthContextToPrincipal({ tokenType: "None" });
14907
- return runWithAuth(userIdentity, fn, principal2);
15156
+ const executionAuth = resolveExecutionAuth(auth);
15157
+ return runWithAuth(executionAuth.userIdentity, fn, executionAuth.authContext);
14908
15158
  }
14909
15159
  get docstore() {
14910
15160
  return this.services.docstore;
@@ -14920,27 +15170,32 @@ class InlineUdfExecutor {
14920
15170
  }
14921
15171
  async execute(functionPath, args, udfType, auth, componentPath, requestId, snapshotTimestamp) {
14922
15172
  const bootstrapTiming = await this.ensureBootstrapped();
14923
- const [moduleName, functionName2] = this.parseUdfPath(functionPath);
14924
- const finalRequestId = requestId ?? this.requestIdFactory(udfType, functionPath);
14925
- const isSystemFunction = moduleName === "_system" || functionPath.startsWith("_system:");
15173
+ const target = normalizeUdfFunctionTarget(functionPath, {
15174
+ componentPath,
15175
+ policy: { allowFunctionHandle: true }
15176
+ });
15177
+ const { modulePath: moduleName, exportName: functionName2 } = target;
15178
+ const finalRequestId = requestId ?? this.requestIdFactory(udfType, target.path);
15179
+ const executionAuth = resolveExecutionAuth(auth);
15180
+ const isSystemFunction = moduleName === "_system" || target.path.startsWith("_system:");
14926
15181
  const startTime = performance.now();
14927
15182
  const invokeUdf = async () => {
14928
- const module = await withTraceSpan("udf.load_module", "runtime", () => this.loadModule(moduleName, componentPath), { moduleName, componentPath: componentPath ?? "" });
15183
+ const module = await withTraceSpan("udf.load_module", "runtime", () => this.loadModule(moduleName, target.componentPath), { moduleName, componentPath: target.componentPath ?? "" });
14929
15184
  const fn = module?.[functionName2];
14930
- this.assertFunctionExport(functionName2, moduleName, fn, udfType, auth);
14931
- await withTraceSpan("udf.validate_args", "runtime", () => this.validateArgs(fn, args, componentPath), {
15185
+ const resolvedType = this.assertFunctionExport(functionName2, moduleName, fn, udfType, executionAuth.executorAuth);
15186
+ await withTraceSpan("udf.validate_args", "runtime", () => this.validateArgs(fn, args, target.componentPath), {
14932
15187
  moduleName,
14933
15188
  functionName: functionName2,
14934
- componentPath: componentPath ?? ""
15189
+ componentPath: target.componentPath ?? ""
14935
15190
  });
14936
15191
  const argsString = JSON.stringify(convexToJson([args]));
14937
- if (fn.isQuery) {
15192
+ if (resolvedType === "query") {
14938
15193
  return withTraceSpan("udf.invoke_query", "runtime", async () => JSON.parse(await fn.invokeQuery(argsString)), { moduleName, functionName: functionName2 });
14939
15194
  }
14940
- if (fn.isMutation) {
15195
+ if (resolvedType === "mutation") {
14941
15196
  return withTraceSpan("udf.invoke_mutation", "runtime", async () => JSON.parse(await fn.invokeMutation(argsString)), { moduleName, functionName: functionName2 });
14942
15197
  }
14943
- if (fn.isAction) {
15198
+ if (resolvedType === "action") {
14944
15199
  return withTraceSpan("udf.invoke_action", "runtime", async () => JSON.parse(await fn.invokeAction(finalRequestId, argsString)), { moduleName, functionName: functionName2 });
14945
15200
  }
14946
15201
  throw new Error(`Function "${functionName2}" has no valid type`);
@@ -14950,15 +15205,15 @@ class InlineUdfExecutor {
14950
15205
  type: udfType,
14951
15206
  docstore: this.docstore,
14952
15207
  fn: invokeUdf,
14953
- auth,
15208
+ auth: executionAuth.executorAuth,
14954
15209
  storage: this.blobstore,
14955
15210
  searchstore: this.searchstore,
14956
15211
  vecstore: this.vecstore,
14957
15212
  requestId: finalRequestId,
14958
15213
  udfExecutor: this,
14959
- componentPath,
15214
+ componentPath: target.componentPath,
14960
15215
  snapshotOverride: udfType === "query" ? snapshotTimestamp : undefined,
14961
- functionPath,
15216
+ functionPath: target.path,
14962
15217
  tableRegistry: this.tableRegistry
14963
15218
  });
14964
15219
  };
@@ -14969,7 +15224,7 @@ class InlineUdfExecutor {
14969
15224
  const duration = performance.now() - startTime;
14970
15225
  const logEntry = {
14971
15226
  timestamp: Date.now(),
14972
- functionName: functionPath,
15227
+ functionName: target.path,
14973
15228
  functionType: udfType,
14974
15229
  status: "success",
14975
15230
  duration: Math.round(duration * 100) / 100,
@@ -15028,6 +15283,7 @@ class InlineUdfExecutor {
15028
15283
  }
15029
15284
  const runHttpUdf = () => resolvedRoute.handler.invokeHttpAction(request);
15030
15285
  const finalRequestId = requestId ?? this.requestIdFactory("http", `${request.method}:${url.pathname}`);
15286
+ const executionAuth = resolveExecutionAuth(auth);
15031
15287
  const functionPath = `${request.method} ${url.pathname}`;
15032
15288
  const startTime = performance.now();
15033
15289
  const recordHttpExecution = (status, extra) => {
@@ -15057,9 +15313,9 @@ class InlineUdfExecutor {
15057
15313
  try {
15058
15314
  const response = await this.withAmbientAuth(auth, async () => {
15059
15315
  if (!this.moduleRegistry) {
15060
- return runUdfHttpAction(this.docstore, runHttpUdf, auth, this.blobstore, this.searchstore, this.vecstore, finalRequestId, this, resolvedRoute.componentPath);
15316
+ return runUdfHttpAction(this.docstore, runHttpUdf, executionAuth.executorAuth, this.blobstore, this.searchstore, this.vecstore, finalRequestId, this, resolvedRoute.componentPath);
15061
15317
  }
15062
- return withModuleRegistry(this.moduleRegistry, () => runUdfHttpAction(this.docstore, runHttpUdf, auth, this.blobstore, this.searchstore, this.vecstore, finalRequestId, this, resolvedRoute.componentPath));
15318
+ return withModuleRegistry(this.moduleRegistry, () => runUdfHttpAction(this.docstore, runHttpUdf, executionAuth.executorAuth, this.blobstore, this.searchstore, this.vecstore, finalRequestId, this, resolvedRoute.componentPath));
15063
15319
  });
15064
15320
  recordHttpExecution("success", { statusCode: response.status });
15065
15321
  return response;
@@ -15153,23 +15409,21 @@ class InlineUdfExecutor {
15153
15409
  }
15154
15410
  }
15155
15411
  parseUdfPath(functionPath) {
15156
- const parts = functionPath.split(":");
15157
- if (parts.length !== 2) {
15158
- throw new Error(`Invalid UDF path: ${functionPath}`);
15159
- }
15160
- return [parts[0], parts[1]];
15412
+ const target = normalizeUdfFunctionTarget(functionPath);
15413
+ return [target.modulePath, target.exportName];
15161
15414
  }
15162
15415
  assertFunctionExport(functionName2, moduleName, fn, udfType, auth) {
15163
15416
  if (typeof fn !== "function") {
15164
15417
  throw new Error(`Function "${functionName2}" not found in module "${moduleName}"`);
15165
15418
  }
15166
- if (udfType === "query" && !fn.isQuery) {
15419
+ const actualType = classifyUdfFunction(fn);
15420
+ if (udfType === "query" && actualType !== "query") {
15167
15421
  throw new Error(`Function "${functionName2}" is not a query`);
15168
15422
  }
15169
- if (udfType === "mutation" && !fn.isMutation) {
15423
+ if (udfType === "mutation" && actualType !== "mutation") {
15170
15424
  throw new Error(`Function "${functionName2}" is not a mutation`);
15171
15425
  }
15172
- if (udfType === "action" && !fn.isAction) {
15426
+ if (udfType === "action" && actualType !== "action") {
15173
15427
  throw new Error(`Function "${functionName2}" is not an action`);
15174
15428
  }
15175
15429
  if (fn.isInternal) {
@@ -15180,6 +15434,7 @@ class InlineUdfExecutor {
15180
15434
  throw new InternalFunctionAccessError(functionPath);
15181
15435
  }
15182
15436
  }
15437
+ return udfType;
15183
15438
  }
15184
15439
  async validateArgs(fn, args, componentPath) {
15185
15440
  const callContext2 = getCallContext();
@@ -15339,7 +15594,7 @@ init_analysis();
15339
15594
  init_module_loader();
15340
15595
  // ../core/dist/udf/execution-adapter.js
15341
15596
  init_auth_context();
15342
- init_jwt();
15597
+ init_execution_auth();
15343
15598
  // ../core/dist/http/api-router.js
15344
15599
  init_auth();
15345
15600
  init_auth_resolver();
@@ -15776,7 +16031,7 @@ class ScheduledFunctionExecutor {
15776
16031
  return [];
15777
16032
  }
15778
16033
  const tables = new Set;
15779
- for await (const entry of this.docstore.load_documents({
16034
+ for await (const entry of this.docstore.loadDocuments({
15780
16035
  min_timestamp_inclusive: sinceExclusive + 1n,
15781
16036
  max_timestamp_exclusive: maxTimestamp + 1n
15782
16037
  }, Order.Asc)) {
@@ -16454,10 +16709,10 @@ class BaseSqliteDocStore {
16454
16709
  }
16455
16710
  }
16456
16711
  }
16457
- async index_scan_rows(indexId, tableId, readTimestamp, interval, order, limit) {
16712
+ async indexScanRows(indexId, tableId, readTimestamp, interval, order, limit) {
16458
16713
  return this.scanIndexRows(indexId, tableId, readTimestamp, interval, order, limit);
16459
16714
  }
16460
- async index_scan_rows_after_key(indexId, tableId, readTimestamp, interval, order, resumeAfterKey, limit) {
16715
+ async indexScanRowsAfterKey(indexId, tableId, readTimestamp, interval, order, resumeAfterKey, limit) {
16461
16716
  return this.scanIndexRows(indexId, tableId, readTimestamp, interval, order, limit, resumeAfterKey);
16462
16717
  }
16463
16718
  async scanIndexRows(indexId, tableId, readTimestamp, interval, order, limit, resumeAfterKey) {
@@ -16559,13 +16814,13 @@ class BaseSqliteDocStore {
16559
16814
  }
16560
16815
  return results;
16561
16816
  }
16562
- async* index_scan(indexId, tabletId, readTimestamp, interval, order, limit) {
16563
- const rows = await this.index_scan_rows(indexId, tabletId, readTimestamp, interval, order, limit);
16817
+ async* indexScan(indexId, tabletId, readTimestamp, interval, order, limit) {
16818
+ const rows = await this.indexScanRows(indexId, tabletId, readTimestamp, interval, order, limit);
16564
16819
  for (const row of rows) {
16565
16820
  yield row;
16566
16821
  }
16567
16822
  }
16568
- async* load_documents(range, order) {
16823
+ async* loadDocuments(range, order) {
16569
16824
  const orderClause = order === Order.Asc ? "ASC" : "DESC";
16570
16825
  const query = `
16571
16826
  SELECT id, ts, table_id, json_value, deleted, prev_ts
@@ -16603,7 +16858,7 @@ class BaseSqliteDocStore {
16603
16858
  const rows = await stmt.all(key, JSON.stringify(value));
16604
16859
  return rows.length > 0;
16605
16860
  }
16606
- async previous_revisions(queries) {
16861
+ async previousRevisions(queries) {
16607
16862
  const results = new Map;
16608
16863
  const stmt = this.getPreparedStatement(`
16609
16864
  SELECT ts, json_value, deleted, prev_ts
@@ -16628,7 +16883,7 @@ class BaseSqliteDocStore {
16628
16883
  }
16629
16884
  return results;
16630
16885
  }
16631
- async previous_revisions_of_documents(queries) {
16886
+ async previousRevisionsOfDocuments(queries) {
16632
16887
  const results = new Map;
16633
16888
  const stmt = this.getPreparedStatement(`
16634
16889
  SELECT ts, json_value, deleted, prev_ts
@@ -16685,7 +16940,7 @@ class BaseSqliteDocStore {
16685
16940
  prev_ts: row.prev_ts != null ? BigInt(row.prev_ts) : null
16686
16941
  };
16687
16942
  }
16688
- async get_many(ids, readTimestamp) {
16943
+ async getMany(ids, readTimestamp) {
16689
16944
  const results = new Map;
16690
16945
  if (ids.length === 0) {
16691
16946
  return results;