Repository navigation
Studio Access pillar: package-level OWD overview — audit & batch-edit sharingModel across all objects in a package #2505
Description
Problem
For a package author, the record-sharing baseline (OWD, sharingModel / externalSharingModel) of the package's objects can only be inspected and edited one object at a time, via the Data pillar → object → Settings tab (ObjectSettingsPanel.tsx). The permission matrix (PermissionMatrixEditor.tsx) shows a read-only OWD badge per object row, but offers no way to change it and no package-wide view.
Consequences:
- A package with 20 objects requires opening 20 settings pages to audit its baseline posture. In practice this means nobody audits it: in the
com.example.showcasedogfood app, most objects sit atpublic_read_writewhile a few areprivate, and this imbalance is invisible from any single screen. - ADR-0090 D1 made explicit OWD mandatory precisely because the silent-widening failure class (objectui#2348) is invisible object-by-object. A per-object-only editing surface leaves the review side of that decision unsupported: there is no screen on which "which of my objects are org-wide writable?" can be answered at a glance.
- The
externalSharingModel ≤ sharingModelconstraint (ADR-0090 D11) is validated per object at authoring/lint time, but an author can't survey the external dimension across the package before publish.
Proposal
Add a package-scoped "Record Sharing Baseline (OWD)" panel to the Studio Access pillar, as a sibling surface next to the permission-set rail (not inside the permission matrix):
- A table of object ×
sharingModel×externalSharingModelcovering every object owned by the current package (published ∪ pending drafts, same merge the pillars already do). - Inline select per cell using the canonical four values (
private | public_read | public_read_write | controlled_by_parent), reusing the option labels/help copy fromObjectSettingsPaneland the badge/i18n helpers fromviews/metadata-admin(owdLabel,views/metadata-admin/i18n.ts). controlled_by_parentrows display the master link (read-only) instead of an external dial, mirroring the per-object settings behavior.- Row-level validation
external ≤ internal(theOWD_WIDTHcomparison already implemented inObjectSettingsPanel.tsx) surfaced inline before save. - Save = per-object metadata drafts under the package scope — exactly what the per-object Settings tab writes today, just N objects in one action. Publish then flows through the existing security-domain gate unchanged (ADR-0090 D7 lint + human gate; the D6 semantic diff is naturally per-row: "
showcase_contactwidensprivate→public_read"). - Deep-linkable via the existing
?surface=plumbing (useSurfaceDeepLink), so the read-only OWD badge in the permission matrix can link here.
Why this does not blur the ADR-0090 concept boundaries
Merging OWD into the permission-set matrix was considered and rejected (ADR-0090; permission sets are additive per-principal unions, OWD is a per-object scalar baseline with a different owner). This proposal is not that: every row in this table has the same owner — the package author ("OWD: object author · sharing: environment", docs/design/permission-model.md). It is an aggregation of N editing entry points within one ownership boundary, not a merge of two concepts. It has no principal dimension and binds to nobody.
Non-goals
- No package-level default OWD with inheritance. The table batch-edits N explicit per-object values. A package default that objects inherit would reintroduce the ambient "unset" state ADR-0090 D1 abolished.
- Not merging OWD editing into the permission-set matrix. The matrix keeps its read-only badge (now linkable).
enable.*capability switches are out of scope. The same ownership argument supports a package-level "object × capability switch" overview, but those are behavior config, not authorization — if pursued, it belongs in the Data pillar as a follow-up issue.- No changes to enforcement, lint rules, or the publish pipeline — this is purely an authoring-surface addition.
Implementation notes
- Entry point:
StudioDesignSurface.tsx→AccessPillar(rail pattern,?surface=deep-link,publishNoncere-read after publish are all established there). - Reuse: OWD select options + external-dial +
OWD_WIDTHvalidation fromviews/studio-design/ObjectSettingsPanel.tsx(likely extract a shared control); OWD label/i18n fromviews/metadata-admin/i18n.ts. - Data:
client.list('object', { packageId })∪client.listDrafts({ packageId, type: 'object' }); per-object draft save on batch apply; OCC / destructive-change dialog conventions per the existing editors. - Read-only mode must follow the pillar's
readOnlycourtesy gate (package read-only ⇒ table renders badges only).
Acceptance criteria
- Access pillar shows an OWD overview listing all objects of the current package (published ∪ drafts) with internal + external sharing model per row.
- Author can change multiple objects' OWD and save once; each change lands as that object's package-scoped draft; publish goes through the unchanged security-domain gate.
-
external > internalis blocked inline per row;controlled_by_parentrows show the master and no external dial. - The OWD badge in
PermissionMatrixEditordeep-links to this panel. - Read-only packages render the table non-editable.
- ADR-0054 testability proofs for the new surface (list render, edit→draft, validation block, deep-link).
References
- framework ADR-0090 (Permission Model v2 — D1 mandatory explicit OWD, D4 canonical enum, D11 external dial, D6 explain / D7 security-domain gate) and companion
docs/design/permission-model.md - objectui ADR-0056 (permission editing belongs in Studio — "one validated authoring path per concern")
- objectui#2348 (OWD control in Studio + dogfood incident), objectui#2403 (structured permission editors)
Origin: Studio dogfooding of com.example.showcase — auditing the package's record baseline currently requires visiting every object's settings page individually.
Activity
feat(studio-access): package-level OWD overview — audit & batch-e…