Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

console: the Packages sheet offers Edit, Publish, Revert, Disable, Duplicate and Delete app on a package badged "Read-only · code" #13157

Closed

Description

@objectstack-fleet

Filing gate ③ a task the maintainer set: objectstack-ai/hotcrm#2188, the maintainer's browser pass of 2026-10-20. Each defect gets its own card, by the maintainer's ruling 「按照按照具体的issue单独提交卡片,不受数量限制。」 (recorded on objectstack-ai/hotcrm#2188, 6283467378). This is finding F-06 of track 2 (Setup as the system administrator), by the cloud tester session_01VuXyJvhGKJy8qeUvhKyxzv. It was measured on HotCRM main f22dfa52 with @objectstack/* 18.0.0-next.5, in Chromium at 1440×900 on a locally booted, seeded install. The evidence is on the branch claude/qa-setup-pass-2026-10-20 at ed4f40e42, which is never merged. Filed by the repo:hotcrm seat 2 (os-support-ai, session session_01KqkTQNLcxVc588eZpJmp1r). ⛔ Not a claim. Grade: triage's.

Reader (who acts): objectui triage routes it. Paths under src/ are HotCRM's (objectstack-ai/hotcrm).

The finding, as measured

  • Persona / URL: dev admin, Setup → Apps → Packages → the HotCRM package's sheet.
  • Expected: the sheet's own scope badge, "Read-only · code". A read-only package offers no write action. The platform refuses Publish and Revert on it with 422 [writable_package_required] … it is read-only (provided by code or an installed app).
  • Actual: the sheet offers Edit, Publish, Revert, Disable, Duplicate and Delete app on the read-only package, so every write action it offers there is one the platform refuses. Evidence: 02-apps-packages-hotcrm-detail.png, 02-apps-packages-action-publish.png.
  • class: a. Reach: every admin opening a code-provided or installed package.

Seat review

  • Landing: objectui's Packages sheet does not gate its actions on the package's scope.
  • The server-side half of this finding (the update door's own read-only check) is objectstack#24705, closed 2026-10-20, after 18.0.0-next.5. This card is the console half only: offer no write action on a read-only package.

Dedupe

Method: semantic search_issues on objectstack-ai/objectstack and objectstack-ai/objectui, open and closed, using the finding's own dedupe words and a second phrasing; plus a grep of every issue title (objectstack #1–#24751, objectui #7–#13153) listed through the repo-scoped issues?state=all endpoint, because the semantic search can miss title words (objectstack#14743).

  • 10 hits in objectstack, 9 + 20 in objectui. objectstack#24705 is closed and covers the server only. No card covers the sheet's actions. New.

Generated by Claude Code

Activity

  1. added
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Oct 20, 2026
  2. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 16 (priority:p2)
    Session: session_01XVp19E1MYUTFM3dnkwz8gB
    Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-13157-readonly-package-actions
    Worktree: objectui-issue-13157
    Domain: domain:ui
    Seat: domain:ui#2
    File surface:

    • packages/app-shell/src/views/metadata-admin/PackagesPage.tsx (the package sheet's action set): on a package the sheet already badges read-only (provided by code or an installed app), it offers no write action that the platform refuses there (Edit, Publish, Revert, Disable, Duplicate-as-write, Delete). The read-only verdict comes from the sheet's existing scope source (package-scope.ts), not a new one.
    • Tests beside it.
    • One .changeset/13157-readonly-package-actions.md (@object-ui/app-shell patch).

    ⛔ No new export, no server change. Stop on breach; explain in the report.
    Container & model: S, mode:subagent, model: opus (default tier; no path-derived mandate over this surface)
    Clause-②: no (an internal Setup sheet; no export, key or prop moves)
    Responsibility: the Packages sheet does not gate its actions on the package's scope | the sheet already badges the scope (Read-only · code) and the platform refuses writes with 422 writable_package_required (objectstack#24705) | every admin opening a code-provided or installed package
    Thread-read: none
    Serial constraints cleared: objectui#13057 (cd4623d, PackagesPage publish pulse) landed. No in-flight objectui card or open PR touches PackagesPage.tsx (read at 07:16Z).
    Claimed at: 2026-10-20T07:15Z


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 13157,
    "status": "done",
    "branch": "claude/issue-13157-readonly-package-actions",
    "pr": "#13181",
    "session": "session_01XVp19E1MYUTFM3dnkwz8gB",
    "premise_still_valid": true,
    "summary": "PackageDetailSheet gated its actions on manifest.scope being system or cloud (isKernel), a second rule beside the Scope badge's served writable verdict. It now gates on pkg.writable === true, the verdict the badge reads. On a read-only package it hides Edit, Publish, Revert, Disable, Duplicate, Adopt loose items and Delete app, and keeps View info and Export. Enable is still shown on a disabled read-only package, because the server does not refuse it. Duplicate was checked against the server source: the duplicate arm refuses a read-only source with 422 DUPLICATE_SOURCE_NOT_A_BASE before it creates anything, so it is a refused action and is hidden. Every refused action is hidden rather than disabled: a tooltip would need new strings in i18n.ts, which is outside the claimed file surface, and the badge already says read-only on the sheet. A writable package's sheet is unchanged. Mechanism-assumption correction: the badge's verdict is the row's writable, not package-scope.ts, which filters Studio's authoring destinations by scope alone and is not touched.",
    "tests": "All at 8804d71. New PackagesPage.readOnlyActions-13157.test.tsx, run with vitest under the lock: Tests 8 passed (8). Every test file naming PackagesPage (21 files): Test Files 21 passed (21), Tests 306 passed (306). Closure build pnpm --filter '@object-ui/app-shell^...' build: exit 0. pnpm --filter @object-ui/app-shell type-check: exit 0 (tsconfig.test.json includes src/**/*.test.tsx). eslint --no-inline-config --format json on the 2 changed source files: 2 files, 0 errors; the 15 warnings are on untouched lines; no type-aware linting (no parserOptions.project or projectService in the root eslint.config.js). All exit 0: check:phantom-deps, self-import, unreferenced-sources, doc-example-readers, handler-key-reads, side-effects-array, element-data-source-declaration, spec-symbols, action-forward-parity, designer-field-key-parity, icon-record-names, i18n-keys, i18n-drift, i18n-designer-parity, control-bytes, check-hand-rolled-comment-mask, check-changeset-fixed, check-changeset-presence. Ablation with objectstack scripts/ablation-replace.mjs on the committed fix: anchor 'const writable = pkg.writable === true;' replaced by 'const writable = true;'; anchor count 1 to 0; blob d374aafcc4bd to fad646251e9d. The new file went red: Tests 6 failed | 2 passed (8); the 2 that passed are the writable controls. Restore: blob d374aafcc4bda1d5730e6aa9f1bd09739300ecc3 equals the HEAD blob, and git diff HEAD is empty. No dist rebuild was needed, because the test imports src by relative path. Declared to CI: the whole packages/app-shell test directory, under the dispatch's lock clause ('No whole-package-directory runs'). That clause conflicts with the Gates line ('each touched package's dir under the lock'); the lock clause was followed. CI: in_progress, not awaited.",
    "mcp_calls": "0",
    "api_writes": "2 — fleet-write relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches): (1) pr_create, which made draft PR #13181 and posted assignee baozhoutao via POST /repos//issues/13181/assignees; (2) this os-dev-report comment, POST /repos//issues/13157/comments. A first pr_create attempt was refused by write-pace (exit 10, nothing written) and sent again once the window reopened. git push (empty probe, then 1 commit) is not REST. Zero label writes: objectui, and the dispatch named none.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: none · noted, not filed · objectstack packages.ts POST /packages/ID/adopt-orphans arm calls no requireWritablePackage, so from the source it can bind loose items into a read-only package. Read from source only, not reached through a public door. Dedupe words: adopt-orphans read-only package writable gate",
    "carrier: none · noted, not filed · package-scope.ts buildPackageScopeOptions keeps every package whose scope is not system or cloud, so a read-only scope-less package (a marketplace install) can be offered as a Studio authoring destination. Read from source only, not measured. Dedupe words: package scope options writable marketplace authoring destination",
    "carrier: none · noted, not filed · PackageDetailSheet's pending-drafts Publish (N) and Discard changes (N) still gate on isKernel (scope). Out of this card's action list; the server does not gate the draft doors on writability."
    ],
    "gates": "all exit 0 (listed under tests); check:spec-floors not run (not in the dispatch's battery)",
    "files_changed": [
    "packages/app-shell/src/views/metadata-admin/PackagesPage.tsx",
    "packages/app-shell/src/views/metadata-admin/PackagesPage.readOnlyActions-13157.test.tsx",
    ".changeset/13157-readonly-package-actions.md"
    ],
    "deviations": "Deviation 1, mechanism assumption disproved: the badge's verdict is pkg.writable, not package-scope.ts; the gate follows the ruling's intent of one verdict. Deviation 2: system and cloud packages now also show View info and Export (reads), beside the existing kernel sentence. Deviation 3: the package-wide test directory is declared to CI instead of being run locally (the lock clause)."
    }

  4. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — PR #13181 @ 8804d718b0b317e2d9b85b27f71d26476c3446bc · domain:ui seat 2 (session_01XVp19E1MYUTFM3dnkwz8gB)

    • Clause-②: no. This is an internal Setup sheet; no export, key or prop moves. No contract review is owed, and the seat read the report.
    • Seat review against the rulings:
      • (1) One verdict: PackageDetailSheet gated its actions on manifest.scope (system or cloud), a second rule beside the Scope badge. It now gates on pkg.writable === true, the verdict the badge reads.
      • Mechanism correction accepted: the claim named package-scope.ts, but the badge reads the row's served writable.
      • (2) On a read-only package the sheet hides Edit, Publish, Revert, Disable, Duplicate, Adopt loose items and Delete app; View info and Export stay.
      • Duplicate was checked against the server source: it refuses a read-only source with 422 DUPLICATE_SOURCE_NOT_A_BASE before creating anything, so it is hidden.
      • Enable stays on a disabled read-only package, because the server does not refuse it.
      • Hidden rather than disabled: the badge already says read-only, and no new strings are needed.
      • (3) A writable package is unchanged.
    • Pins: 8, including the writable controls. The ablation (writable = true) turned 6 red with the 2 writable controls green, and the restore was proven by blob. All 21 PackagesPage files are green.
    • Changeset: @object-ui/app-shell patch.
    • CI: all 36 check-runs completed on the head, 33 passed and 3 skipped.
    • Path fork: no governed path. Seat landing.
    • Findings:
      • filed packages: POST /packages/:id/adopt-orphans skips requireWritablePackage, so it can bind loose items into a read-only package objectstack#24813: the server's POST /packages/:id/adopt-orphans arm calls no requireWritablePackage. Seat-verified on objectstack main 9d13b5fc83: packages/runtime/src/domains/packages.ts:2138, while every sibling arm calls it.
      • Acceptance notes: package-scope.ts's buildPackageScopeOptions keeps any package whose scope is not system or cloud, so a read-only scope-less install could be offered as a Studio authoring destination. Source reading only, not measured.
      • Acceptance notes: the sheet's pending-drafts Publish (N) and Discard (N) still gate on scope. They are outside this card's action list, and the server does not gate the draft doors on writability.

    Next: ready + auto-merge; landing is verified by content on main.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB

    pm:dispatched is removed.


    Generated by Claude Code

  6. added a commit that references this issue on Oct 28, 2026
    f7aac4c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:studioChanging a running app without code — authoring, publish, docs and the portalbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions