Repository navigation
Description
Path: P2 | access-security(permission sets) | 解锁 objectui#5987 的读数请求
objectstack-ai/objectui#5987 is the UI half of the ruling this repo's objectstack#11513 executed
(2026-08-24, 「同意 第一步(创业阶段,Salesforce 式)」 — lock the base, clone to customize). Its body
carries an explicit instruction to whoever takes it: ⛔ do not guess the provenance predicate from
the current row shape. This card is that reading, asked of the lane that owns the producer.
Asked by the domain:ui#2 execution seat at objectstack-ai/objectui
(session_018HrVaotisyhgmot9o2MLRq), 2026-09-19T10:13Z. ⛔ This seat does not grade or route this card.
What this seat already measured, so it is not re-paid
All on objectstack origin/main and the published spec tags, read 2026-09-19T10:13Z:
| reading | value |
|---|---|
| objectstack#11513 (server half) | closed completed; refusal live |
| objectstack#11703 (clone copies 2 of 6 facets) | closed completed |
objectstack#11843 (the OS_METADATA_WRITABLE door probe) |
closed completed |
NOT_OVERRIDABLE in @objectstack/spec@17.4.0 packages/spec/src |
7 |
…in @objectstack/spec@17.3.0 |
7 |
CONTROL — package_id, same corpus and query form |
18 / 18 |
managed_by in @objectstack/spec@17.4.0 packages/spec/src |
8 |
⇒ the refusal code is a declared member of the error-code ledger
(packages/spec/src/api/error-code-ledger.zod.ts:612) and is installable at the version objectui
resolves. ⛔ That half is not what is missing.
⭐ And the card's caution was right — the obvious guess is wrong
packages/plugins/plugin-security/src/security-plugin.ts:5591-:5604, the admin-door gate, keys on
managed_by === 'package':
const existing = await this.readRowById('sys_permission_set', targetId, { isSystem: true });
if (existing && (existing as Record<string, unknown>).managed_by === 'package') {
…
packageId: (row.package_id as string | null) ?? null,⇒ package_id is carried only as context on the refusal, and it is explicitly nullable — :3753
records a publish that 「carried no owning package_id to stamp」. A UI lock keyed on package_id
presence would therefore miss package-managed rows whose package_id is null. That is exactly
the row-shape guess objectui#5987 forbids, and it is the guess a reader makes by default.
⚠️ The two cautions this seat found while reading, which are why it stopped rather than dispatching
managed_by:'package'is NOT the same predicate as 「the server will refuse this write」.
security-plugin.ts:5544-:5551states thatupdate/deleteare not refused at that gate at
all — they are translated into a metadata write and refused by THAT producer, where a
code-declared (artifact-backed) set draws403 NOT_OVERRIDABLEwhile asys_metadata-backed
set 「ridesallowRuntimeCreateand still lands」. ⇒ a UI that hard-locks every
managed_by:'package'row would show a lock on a set the server would have accepted.managed_byis not universally the key.permission-set-overlay-discard.tsand its test
state 「eligibility is NOT gated onmanaged_by」 for the discard path, and
permission-set-projection.tsexists specifically to control which columns a reader sees.
⇒ The reading requested — three questions, all producer-side
- What does a UI reader actually receive? Does
sys_permission_set's projection serve
managed_by(andpackage_id, andcustomized) to a non-system caller through the ordinary
data door, or does it strip them?permission-set-projection.test.ts:285already iterates that
column list, so the answer may be one assertion away. - Which predicate should a UI lock on, given (1):
managed_by === 'package'alone, or that
plus the artifact-backed vssys_metadata-backed distinction that decides whether the write is
actually refused? - Is the refusal legible to a UI? Does the rejected write surface
NOT_OVERRIDABLE(or the
PermissionDeniedErrortext) in a shape objectui can key on, so item 3 of the UI card — 「the
server's refusal is surfaced as the same guidance, not a generic error toast」 — is implementable
without string-matching a prose message?
⛔ This seat did not attempt (1) or (3): they are runtime readings of a producer this seat cannot
stand up, and guessing them is the failure objectui#5987 names in its own body.
⇒ objectstack-ai/objectui#5987 is being set pm:blocked with Blocked-by: naming this card. It is
the oldest p2 product card in that lane and it is otherwise ready.
Dedupe words: sys_permission_set projection managed_by · packaged permission set UI lock predicate ·
NOT_OVERRIDABLE surfaced to UI · managed_by package artifact-backed refusal ·
objectui#5987 provenance reading
Generated by Claude Code
Activity