@objectstack/core 14.8.0 → 15.0.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.cjs CHANGED
@@ -40,6 +40,9 @@ __export(index_exports, {
40
40
  ObjectKernel: () => ObjectKernel,
41
41
  ObjectKernelBase: () => ObjectKernelBase,
42
42
  ObjectLogger: () => ObjectLogger,
43
+ POSTURE_INJECTION_RULE: () => POSTURE_INJECTION_RULE,
44
+ POSTURE_LADDER: () => POSTURE_LADDER,
45
+ POSTURE_RANK: () => POSTURE_RANK,
43
46
  PluginConfigValidator: () => PluginConfigValidator,
44
47
  PluginHealthMonitor: () => PluginHealthMonitor,
45
48
  PluginLoader: () => PluginLoader,
@@ -69,6 +72,7 @@ __export(index_exports, {
69
72
  createPluginPermissionEnforcer: () => createPluginPermissionEnforcer,
70
73
  deepMerge: () => deepMerge,
71
74
  defaultIsTransientError: () => defaultIsTransientError,
75
+ derivePosture: () => derivePosture,
72
76
  evaluateAuthGate: () => evaluateAuthGate,
73
77
  extractApiKey: () => extractApiKey,
74
78
  generateApiKey: () => generateApiKey,
@@ -83,6 +87,7 @@ __export(index_exports, {
83
87
  isNode: () => isNode,
84
88
  parseScopes: () => parseScopes,
85
89
  parseSignature: () => parseSignature,
90
+ postureVisibleRows: () => postureVisibleRows,
86
91
  readAuthoredTranslationLayer: () => readAuthoredTranslationLayer,
87
92
  resolveApiKeyPrincipal: () => resolveApiKeyPrincipal,
88
93
  resolveAuthzContext: () => resolveAuthzContext,
@@ -4243,6 +4248,62 @@ function isGrantExpired(row, nowMs) {
4243
4248
  return !(nowMs < until);
4244
4249
  }
4245
4250
 
4251
+ // src/security/posture-ladder.ts
4252
+ var POSTURE_LADDER = [
4253
+ "PLATFORM_ADMIN",
4254
+ "TENANT_ADMIN",
4255
+ "MEMBER",
4256
+ "EXTERNAL"
4257
+ ];
4258
+ var POSTURE_RANK = {
4259
+ PLATFORM_ADMIN: 3,
4260
+ TENANT_ADMIN: 2,
4261
+ MEMBER: 1,
4262
+ EXTERNAL: 0
4263
+ };
4264
+ var POSTURE_INJECTION_RULE = {
4265
+ PLATFORM_ADMIN: "Layer 0 exemption where the object posture permits (private / platform-global / better-auth-managed) \u2014 crosses the tenant wall; org-scoped like TENANT_ADMIN on ordinary tenant business objects.",
4266
+ TENANT_ADMIN: "All rows within the active organization (organization_id == ctx.tenantId); no ownership / depth / sharing narrowing.",
4267
+ MEMBER: "Business RLS within the organization \u2014 ownership (owner / unit depth), the OWD baseline, and explicit sharing.",
4268
+ EXTERNAL: "Explicitly shared rows ONLY \u2014 OWD baselines and sharing rules never apply; a misconfiguration can only shrink visibility, never widen it."
4269
+ };
4270
+ function derivePosture(evidence) {
4271
+ if (evidence.isPlatformAdmin) return "PLATFORM_ADMIN";
4272
+ if (evidence.isTenantAdmin) return "TENANT_ADMIN";
4273
+ return "MEMBER";
4274
+ }
4275
+ function isSharedTo(row, userId) {
4276
+ return (row.sharedTo ?? []).includes(userId);
4277
+ }
4278
+ function externalVisible(rows, p) {
4279
+ return rows.filter((r) => isSharedTo(r, p.userId));
4280
+ }
4281
+ function memberVisible(rows, p) {
4282
+ const shared = new Set(externalVisible(rows, p));
4283
+ return rows.filter(
4284
+ (r) => shared.has(r) || r.organization_id === p.organizationId && (r.owner_id === p.userId || r.owdVisible === true)
4285
+ );
4286
+ }
4287
+ function tenantAdminVisible(rows, p) {
4288
+ const member = new Set(memberVisible(rows, p));
4289
+ return rows.filter((r) => member.has(r) || r.organization_id === p.organizationId);
4290
+ }
4291
+ function platformAdminVisible(rows) {
4292
+ return [...rows];
4293
+ }
4294
+ function postureVisibleRows(posture, rows, principal) {
4295
+ switch (posture) {
4296
+ case "PLATFORM_ADMIN":
4297
+ return platformAdminVisible(rows);
4298
+ case "TENANT_ADMIN":
4299
+ return tenantAdminVisible(rows, principal);
4300
+ case "MEMBER":
4301
+ return memberVisible(rows, principal);
4302
+ case "EXTERNAL":
4303
+ return externalVisible(rows, principal);
4304
+ }
4305
+ }
4306
+
4246
4307
  // src/security/resolve-authz-context.ts
4247
4308
  function safeJsonParse2(s, fallback) {
4248
4309
  try {
@@ -4389,6 +4450,10 @@ async function resolveAuthzContext(input) {
4389
4450
  if (hasPlatformAdminGrant && !ctx.positions.includes(import_spec.BUILTIN_IDENTITY_PLATFORM_ADMIN)) {
4390
4451
  ctx.positions.unshift(import_spec.BUILTIN_IDENTITY_PLATFORM_ADMIN);
4391
4452
  }
4453
+ ctx.posture = derivePosture({
4454
+ isPlatformAdmin: hasPlatformAdminGrant,
4455
+ isTenantAdmin: ctx.permissions.includes(import_spec.ORGANIZATION_ADMIN)
4456
+ });
4392
4457
  if (!ctx.permissions.includes("ai_seat")) {
4393
4458
  const aiAccess = (await getUserRow())?.ai_access;
4394
4459
  if (aiAccess === true || aiAccess === 1 || aiAccess === "1") ctx.permissions.push("ai_seat");
@@ -5505,6 +5570,9 @@ var NamespaceResolver = class {
5505
5570
  ObjectKernel,
5506
5571
  ObjectKernelBase,
5507
5572
  ObjectLogger,
5573
+ POSTURE_INJECTION_RULE,
5574
+ POSTURE_LADDER,
5575
+ POSTURE_RANK,
5508
5576
  PluginConfigValidator,
5509
5577
  PluginHealthMonitor,
5510
5578
  PluginLoader,
@@ -5534,6 +5602,7 @@ var NamespaceResolver = class {
5534
5602
  createPluginPermissionEnforcer,
5535
5603
  deepMerge,
5536
5604
  defaultIsTransientError,
5605
+ derivePosture,
5537
5606
  evaluateAuthGate,
5538
5607
  extractApiKey,
5539
5608
  generateApiKey,
@@ -5548,6 +5617,7 @@ var NamespaceResolver = class {
5548
5617
  isNode,
5549
5618
  parseScopes,
5550
5619
  parseSignature,
5620
+ postureVisibleRows,
5551
5621
  readAuthoredTranslationLayer,
5552
5622
  resolveApiKeyPrincipal,
5553
5623
  resolveAuthzContext,