From 9459b4014557928b5a74baa43d9d1cce5a10f2b6 Mon Sep 17 00:00:00 2001 From: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Date: Sun, 28 Jun 2026 02:42:16 +0800 Subject: [PATCH] docs(skill): document env-global / admin-only object visibility posture (objectstack-data) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The objectstack-data skill documented tenancy modes + RLS but not the non-obvious interaction surfaced by cloud#551: a platform admin's viewAllRecords superuser bypass is posture-gated (only fires for access.default:'private' or tenancy.enabled:false), so env-global adapter-written objects (e.g. sys_sso_provider) render an empty list under member_default's wildcard tenant_isolation. Documents the correct recipe — tenancy.enabled:false + requiredPermissions — and the two single-flag pitfalls (leak / admin-blind). Co-Authored-By: Claude Opus 4.8 --- skills/objectstack-data/SKILL.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/skills/objectstack-data/SKILL.md b/skills/objectstack-data/SKILL.md index f323b2d9f4..b9e96f5fc9 100644 --- a/skills/objectstack-data/SKILL.md +++ b/skills/objectstack-data/SKILL.md @@ -586,6 +586,36 @@ enforces per-tenant data isolation: | `isolated` | Separate database per tenant | Regulatory isolation / large tenants | | `hybrid` | Shared schema, tenant-specific sharding | High-volume multi-tenant | +### Platform-global / admin-only objects (visibility posture) + +Some system/config objects are **env-global** (not partitioned per org) and +should be visible to a **platform admin env-wide** but hidden from members — +e.g. identity tables a plugin writes via its own adapter (`sys_sso_provider`, +OAuth clients). These hit a non-obvious interaction: + +- The default `member_default` ships a **wildcard `tenant_isolation` RLS** + (`organization_id == current_user.organization_id`). Any row whose + `organization_id` is **null or absent** (common for adapter-written rows that + never get the tenant stamp) is **denied** — the list renders empty. +- A platform admin's `viewAllRecords` superuser bypass is **posture-gated**: it + fires **only** for objects marked `access.default: 'private'` **or** + `tenancy: { enabled: false }`. On ordinary tenant objects it deliberately does + **not** grant cross-tenant visibility — so the admin sees 0 rows too. + +**Recipe — env-global, admin-only object that admins can fully see:** + +```typescript +tenancy: { enabled: false, strategy: 'shared' }, // env IS the tenant; admin viewAllRecords bypass applies +requiredPermissions: ['manage_platform_settings'], // object-level gate → members get 403 +``` + +> ⚠️ **Don't use either flag alone.** `tenancy.enabled:false` *by itself* drops +> the wildcard RLS, and `member_default`'s `'*': allowRead` then **leaks every +> row to all authenticated users**. `access.default:'private'` *by itself* opts +> the admin's `'*'` grant out too, so the **admin sees nothing**. The +> `tenancy.enabled:false` + `requiredPermissions` pair is the correct combo +> (admin sees all, non-admins 403). Posture model: [ADR-0066](../../docs/adr/0066-unified-authorization-model.md). + ### Cross-skill notes - **API auth providers** (OIDC, JWT, API key) live in **objectstack-api**.