@objectstack/core 14.3.0 → 14.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1808,6 +1808,25 @@ declare function isAuthGateAllowlisted(rawPath: string | undefined | null): bool
1808
1808
  */
1809
1809
  declare function evaluateAuthGate(sessionUser: any, path: string): AuthGate | null;
1810
1810
 
1811
+ /** The validity-window shape shared by both user-grant tables (ADR-0091 D1). */
1812
+ interface GrantValidityWindow {
1813
+ valid_from?: unknown;
1814
+ valid_until?: unknown;
1815
+ }
1816
+ /**
1817
+ * True when a grant row is inside its validity window at `nowMs`.
1818
+ * The single predicate every resolver uses (ADR-0091 D2):
1819
+ * `(valid_from is null or valid_from <= now) and (valid_until is null or valid_until > now)`.
1820
+ */
1821
+ declare function isGrantActive(row: GrantValidityWindow | null | undefined, nowMs: number): boolean;
1822
+ /**
1823
+ * True when a grant row carries a `valid_until` that has already passed —
1824
+ * i.e. it WAS active and expired (not merely not-yet-active). The explain
1825
+ * engine uses this to report the dedicated "held until … — expired"
1826
+ * contributor state (ADR-0091 D2).
1827
+ */
1828
+ declare function isGrantExpired(row: GrantValidityWindow | null | undefined, nowMs: number): boolean;
1829
+
1811
1830
  /**
1812
1831
  * Environment utilities for universal (Node/Browser) compatibility.
1813
1832
  */
@@ -2375,4 +2394,4 @@ declare class NamespaceResolver {
2375
2394
  private suggestAlternative;
2376
2395
  }
2377
2396
 
2378
- export { API_KEY_PREFIX, type ApiKeyPrincipal, ApiRegistry, type ApiRegistryPluginConfig, type AuthGate, type BulkWriteOptions, type BulkWriteRowResult, CORE_FALLBACK_FACTORIES, type CalendarParts, DependencyResolver, type GeneratedApiKey, HotReloadManager, type KernelState, type KeyInput, LiteKernel, type NamespaceCheckResult, type NamespaceConflict, type NamespaceEntry, NamespaceResolver, ObjectKernel, ObjectKernelBase, type ObjectKernelConfig, ObjectLogger, type ParsedSignature, type PermissionCheckResult$1 as PermissionCheckResult, type PermissionGrant, type Plugin, type PluginArtifactVerifyResult, PluginConfigValidator, type PluginContext, PluginHealthMonitor, type PluginHealthStatus, type PluginLoadResult, PluginLoader, type PluginMetadata, type PermissionCheckResult as PluginPermissionCheckResult, PluginPermissionEnforcer, PluginPermissionManager, type PluginPermissions, PluginSandboxRuntime, PluginSecurityScanner, type PluginSignatureConfig, PluginSignatureVerifier, type PluginStartupResult, type PublisherVerifyResult, index as QA, type ResolveAuthzInput, type ResolveLocalizationInput, type ResolvedAuthzContext, type ResourceUsage, type RetryOptions, SIGNATURE_ALG, type SandboxContext, type ScanTarget, SecurePluginContext, type SecurityIssue, SemanticVersionManager, type ServiceFactory, ServiceLifecycle, type ServiceRegistration, type SignatureVerificationResult, type VersionCompatibility, buildPermissionsFromGrants, bulkWrite, calendarPartsInTz, calendarPartsInTzOrUtc, counterSignPayload, createApiRegistryPlugin, createMemoryCache, createMemoryI18n, createMemoryJob, createMemoryMetadata, createMemoryQueue, createPluginConfigValidator, createPluginPermissionEnforcer, deepMerge, defaultIsTransientError, evaluateAuthGate, extractApiKey, generateApiKey, generateEd25519KeyPair, getEnv, getMemoryUsage, hashApiKey, isAuthGateAllowlisted, isExpired, isNode, parseScopes, parseSignature, readAuthoredTranslationLayer, resolveApiKeyPrincipal, resolveAuthzContext, resolveLocale, resolveLocalizationContext, safeExit, signPayload, verifyPayload, verifyPlatformSignature, verifyPluginArtifact, verifyPublisherSignature, wireAuthoredTranslationSync, withTransientRetry };
2397
+ export { API_KEY_PREFIX, type ApiKeyPrincipal, ApiRegistry, type ApiRegistryPluginConfig, type AuthGate, type BulkWriteOptions, type BulkWriteRowResult, CORE_FALLBACK_FACTORIES, type CalendarParts, DependencyResolver, type GeneratedApiKey, type GrantValidityWindow, HotReloadManager, type KernelState, type KeyInput, LiteKernel, type NamespaceCheckResult, type NamespaceConflict, type NamespaceEntry, NamespaceResolver, ObjectKernel, ObjectKernelBase, type ObjectKernelConfig, ObjectLogger, type ParsedSignature, type PermissionCheckResult$1 as PermissionCheckResult, type PermissionGrant, type Plugin, type PluginArtifactVerifyResult, PluginConfigValidator, type PluginContext, PluginHealthMonitor, type PluginHealthStatus, type PluginLoadResult, PluginLoader, type PluginMetadata, type PermissionCheckResult as PluginPermissionCheckResult, PluginPermissionEnforcer, PluginPermissionManager, type PluginPermissions, PluginSandboxRuntime, PluginSecurityScanner, type PluginSignatureConfig, PluginSignatureVerifier, type PluginStartupResult, type PublisherVerifyResult, index as QA, type ResolveAuthzInput, type ResolveLocalizationInput, type ResolvedAuthzContext, type ResourceUsage, type RetryOptions, SIGNATURE_ALG, type SandboxContext, type ScanTarget, SecurePluginContext, type SecurityIssue, SemanticVersionManager, type ServiceFactory, ServiceLifecycle, type ServiceRegistration, type SignatureVerificationResult, type VersionCompatibility, buildPermissionsFromGrants, bulkWrite, calendarPartsInTz, calendarPartsInTzOrUtc, counterSignPayload, createApiRegistryPlugin, createMemoryCache, createMemoryI18n, createMemoryJob, createMemoryMetadata, createMemoryQueue, createPluginConfigValidator, createPluginPermissionEnforcer, deepMerge, defaultIsTransientError, evaluateAuthGate, extractApiKey, generateApiKey, generateEd25519KeyPair, getEnv, getMemoryUsage, hashApiKey, isAuthGateAllowlisted, isExpired, isGrantActive, isGrantExpired, isNode, parseScopes, parseSignature, readAuthoredTranslationLayer, resolveApiKeyPrincipal, resolveAuthzContext, resolveLocale, resolveLocalizationContext, safeExit, signPayload, verifyPayload, verifyPlatformSignature, verifyPluginArtifact, verifyPublisherSignature, wireAuthoredTranslationSync, withTransientRetry };
package/dist/index.d.ts CHANGED
@@ -1808,6 +1808,25 @@ declare function isAuthGateAllowlisted(rawPath: string | undefined | null): bool
1808
1808
  */
1809
1809
  declare function evaluateAuthGate(sessionUser: any, path: string): AuthGate | null;
1810
1810
 
1811
+ /** The validity-window shape shared by both user-grant tables (ADR-0091 D1). */
1812
+ interface GrantValidityWindow {
1813
+ valid_from?: unknown;
1814
+ valid_until?: unknown;
1815
+ }
1816
+ /**
1817
+ * True when a grant row is inside its validity window at `nowMs`.
1818
+ * The single predicate every resolver uses (ADR-0091 D2):
1819
+ * `(valid_from is null or valid_from <= now) and (valid_until is null or valid_until > now)`.
1820
+ */
1821
+ declare function isGrantActive(row: GrantValidityWindow | null | undefined, nowMs: number): boolean;
1822
+ /**
1823
+ * True when a grant row carries a `valid_until` that has already passed —
1824
+ * i.e. it WAS active and expired (not merely not-yet-active). The explain
1825
+ * engine uses this to report the dedicated "held until … — expired"
1826
+ * contributor state (ADR-0091 D2).
1827
+ */
1828
+ declare function isGrantExpired(row: GrantValidityWindow | null | undefined, nowMs: number): boolean;
1829
+
1811
1830
  /**
1812
1831
  * Environment utilities for universal (Node/Browser) compatibility.
1813
1832
  */
@@ -2375,4 +2394,4 @@ declare class NamespaceResolver {
2375
2394
  private suggestAlternative;
2376
2395
  }
2377
2396
 
2378
- export { API_KEY_PREFIX, type ApiKeyPrincipal, ApiRegistry, type ApiRegistryPluginConfig, type AuthGate, type BulkWriteOptions, type BulkWriteRowResult, CORE_FALLBACK_FACTORIES, type CalendarParts, DependencyResolver, type GeneratedApiKey, HotReloadManager, type KernelState, type KeyInput, LiteKernel, type NamespaceCheckResult, type NamespaceConflict, type NamespaceEntry, NamespaceResolver, ObjectKernel, ObjectKernelBase, type ObjectKernelConfig, ObjectLogger, type ParsedSignature, type PermissionCheckResult$1 as PermissionCheckResult, type PermissionGrant, type Plugin, type PluginArtifactVerifyResult, PluginConfigValidator, type PluginContext, PluginHealthMonitor, type PluginHealthStatus, type PluginLoadResult, PluginLoader, type PluginMetadata, type PermissionCheckResult as PluginPermissionCheckResult, PluginPermissionEnforcer, PluginPermissionManager, type PluginPermissions, PluginSandboxRuntime, PluginSecurityScanner, type PluginSignatureConfig, PluginSignatureVerifier, type PluginStartupResult, type PublisherVerifyResult, index as QA, type ResolveAuthzInput, type ResolveLocalizationInput, type ResolvedAuthzContext, type ResourceUsage, type RetryOptions, SIGNATURE_ALG, type SandboxContext, type ScanTarget, SecurePluginContext, type SecurityIssue, SemanticVersionManager, type ServiceFactory, ServiceLifecycle, type ServiceRegistration, type SignatureVerificationResult, type VersionCompatibility, buildPermissionsFromGrants, bulkWrite, calendarPartsInTz, calendarPartsInTzOrUtc, counterSignPayload, createApiRegistryPlugin, createMemoryCache, createMemoryI18n, createMemoryJob, createMemoryMetadata, createMemoryQueue, createPluginConfigValidator, createPluginPermissionEnforcer, deepMerge, defaultIsTransientError, evaluateAuthGate, extractApiKey, generateApiKey, generateEd25519KeyPair, getEnv, getMemoryUsage, hashApiKey, isAuthGateAllowlisted, isExpired, isNode, parseScopes, parseSignature, readAuthoredTranslationLayer, resolveApiKeyPrincipal, resolveAuthzContext, resolveLocale, resolveLocalizationContext, safeExit, signPayload, verifyPayload, verifyPlatformSignature, verifyPluginArtifact, verifyPublisherSignature, wireAuthoredTranslationSync, withTransientRetry };
2397
+ export { API_KEY_PREFIX, type ApiKeyPrincipal, ApiRegistry, type ApiRegistryPluginConfig, type AuthGate, type BulkWriteOptions, type BulkWriteRowResult, CORE_FALLBACK_FACTORIES, type CalendarParts, DependencyResolver, type GeneratedApiKey, type GrantValidityWindow, HotReloadManager, type KernelState, type KeyInput, LiteKernel, type NamespaceCheckResult, type NamespaceConflict, type NamespaceEntry, NamespaceResolver, ObjectKernel, ObjectKernelBase, type ObjectKernelConfig, ObjectLogger, type ParsedSignature, type PermissionCheckResult$1 as PermissionCheckResult, type PermissionGrant, type Plugin, type PluginArtifactVerifyResult, PluginConfigValidator, type PluginContext, PluginHealthMonitor, type PluginHealthStatus, type PluginLoadResult, PluginLoader, type PluginMetadata, type PermissionCheckResult as PluginPermissionCheckResult, PluginPermissionEnforcer, PluginPermissionManager, type PluginPermissions, PluginSandboxRuntime, PluginSecurityScanner, type PluginSignatureConfig, PluginSignatureVerifier, type PluginStartupResult, type PublisherVerifyResult, index as QA, type ResolveAuthzInput, type ResolveLocalizationInput, type ResolvedAuthzContext, type ResourceUsage, type RetryOptions, SIGNATURE_ALG, type SandboxContext, type ScanTarget, SecurePluginContext, type SecurityIssue, SemanticVersionManager, type ServiceFactory, ServiceLifecycle, type ServiceRegistration, type SignatureVerificationResult, type VersionCompatibility, buildPermissionsFromGrants, bulkWrite, calendarPartsInTz, calendarPartsInTzOrUtc, counterSignPayload, createApiRegistryPlugin, createMemoryCache, createMemoryI18n, createMemoryJob, createMemoryMetadata, createMemoryQueue, createPluginConfigValidator, createPluginPermissionEnforcer, deepMerge, defaultIsTransientError, evaluateAuthGate, extractApiKey, generateApiKey, generateEd25519KeyPair, getEnv, getMemoryUsage, hashApiKey, isAuthGateAllowlisted, isExpired, isGrantActive, isGrantExpired, isNode, parseScopes, parseSignature, readAuthoredTranslationLayer, resolveApiKeyPrincipal, resolveAuthzContext, resolveLocale, resolveLocalizationContext, safeExit, signPayload, verifyPayload, verifyPlatformSignature, verifyPluginArtifact, verifyPublisherSignature, wireAuthoredTranslationSync, withTransientRetry };
package/dist/index.js CHANGED
@@ -4138,6 +4138,33 @@ import {
4138
4138
  BUILTIN_IDENTITY_PLATFORM_ADMIN,
4139
4139
  ADMIN_FULL_ACCESS
4140
4140
  } from "@objectstack/spec";
4141
+
4142
+ // src/security/grant-validity.ts
4143
+ function toEpochMs(value) {
4144
+ if (value == null || value === "") return void 0;
4145
+ if (typeof value === "number") {
4146
+ return value < 1e12 ? value * 1e3 : value;
4147
+ }
4148
+ if (value instanceof Date) return value.getTime();
4149
+ if (typeof value === "string") return Date.parse(value);
4150
+ return Number.NaN;
4151
+ }
4152
+ function isGrantActive(row, nowMs) {
4153
+ if (!row) return false;
4154
+ const from = toEpochMs(row.valid_from ?? row.validFrom);
4155
+ if (from !== void 0 && !(nowMs >= from)) return false;
4156
+ const until = toEpochMs(row.valid_until ?? row.validUntil);
4157
+ if (until !== void 0 && !(nowMs < until)) return false;
4158
+ return true;
4159
+ }
4160
+ function isGrantExpired(row, nowMs) {
4161
+ if (!row) return false;
4162
+ const until = toEpochMs(row.valid_until ?? row.validUntil);
4163
+ if (until === void 0) return false;
4164
+ return !(nowMs < until);
4165
+ }
4166
+
4167
+ // src/security/resolve-authz-context.ts
4141
4168
  function safeJsonParse2(s, fallback) {
4142
4169
  try {
4143
4170
  return JSON.parse(s);
@@ -4211,10 +4238,12 @@ async function resolveAuthzContext(input) {
4211
4238
  }
4212
4239
  }
4213
4240
  }
4241
+ const nowMs = input.nowMs ?? Date.now();
4214
4242
  const userPositionRows = await tryFind(ql, "sys_user_position", { user_id: userId }, 200);
4215
4243
  for (const ur of userPositionRows) {
4216
4244
  const org = ur.organization_id ?? null;
4217
4245
  if (org && tenantId && org !== tenantId) continue;
4246
+ if (!isGrantActive(ur, nowMs)) continue;
4218
4247
  const r = ur.position;
4219
4248
  if (typeof r === "string" && r && !ctx.positions.includes(r)) ctx.positions.push(r);
4220
4249
  }
@@ -4228,7 +4257,8 @@ async function resolveAuthzContext(input) {
4228
4257
  } else {
4229
4258
  ctx.org_user_ids = [userId];
4230
4259
  }
4231
- const upsRows = await tryFind(ql, "sys_user_permission_set", { user_id: userId }, 100);
4260
+ const upsRowsAll = await tryFind(ql, "sys_user_permission_set", { user_id: userId }, 100);
4261
+ const upsRows = upsRowsAll.filter((r) => isGrantActive(r, nowMs));
4232
4262
  const psIds = new Set(
4233
4263
  upsRows.filter((r) => {
4234
4264
  const org = r.organization_id ?? r.organizationId ?? null;
@@ -5433,6 +5463,8 @@ export {
5433
5463
  hashApiKey,
5434
5464
  isAuthGateAllowlisted,
5435
5465
  isExpired,
5466
+ isGrantActive,
5467
+ isGrantExpired,
5436
5468
  isNode,
5437
5469
  parseScopes,
5438
5470
  parseSignature,