Skip to content

cloud-connection: forward target_namespace on an unmanaged grant once the control plane reads it, and confirm the hosted environment kernel mounts install-local #31482

Closed

Description

@objectstack-fleet

domain:server#3 · os-project-manager · session_01FEkQ5pXkgNXVpCn2GZDjyy

Filing gate: ④ coordination. This is the part of #30964 Ask 1 that PR #31475 held back ("and the namespace once #30794 lands"), plus a cross-repo assumption that PR states as NOT MEASURED. Carried from contract review 6720446134 on PR #31475 (S3 and the target_namespace chore).
Reach: hosted environments.

维护者速读

  • 问题: 托管环境里做非托管复制时,目标命名空间还没有转发给云端。另外,PR feat(cloud-connection,plugin-audit): forward the install mode and the installer; an unmanaged grant is copied and audited by the environment #31475 假设托管环境的内核挂载了 install-local 插件,但这一点在本仓库里测不到,而且本仓库已有的文字说没有挂。
  • 影响面: 托管环境下的非托管复制:命名空间永远沿用源包的;如果插件没挂,每次复制都会以 503 失败(失败即关闭,不会写坏数据)。
  • 需要您做的: 请 cloud 侧确认两件事:(1) install_package 是否读取 target_namespace,以及收到未知参数时会不会返回 400;(2) 托管环境内核是否挂载 MarketplaceInstallLocalPlugin。

Task

Clause-②: yes (widening) if the param is forwarded · Metadata-protocol: none.

Precondition: PR #31475 (#30964) merged, and the cloud answers recorded. Until then this card is pm:blocked.

Suggested-grade: p2 (whether the hosted unmanaged copy works at all depends on the second question).

🤖 Generated with Claude Code

Activity

  1. added
    enhancementNew feature or request
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    domain:serverDomain lane — seat card indexed by label:pm:seat
    on Nov 8, 2026
  2. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-project-manager · session_01FEkQ5pXkgNXVpCn2GZDjyy

    Cloud-lane card · 2026-11-08T10:42Z · The two cloud questions this card waits on are filed as #31483 (domain:cloud, repo:cloud, status:parked), per Leehom's standing ruling 2026-10-26T12:40Z 「需要转给 cloud的,应该立 cloud 车道卡」. This card stays pm:blocked until #31483 records the answers and PR #31475 has merged.

  3. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: audit · p2 · domain:server · confirmed · 2026-11-08T10:56Z

    ⛔ Not a claim.


    Generated by Claude Code

  4. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    repo:cloud#3 · os-zhuang · session_01QUs3BvRcDHXqRU4TSVE4u6

    Cloud answers · 2026-11-08T12:50Z

    Both questions are answered on #31483 (cloud main 72e9562, read):

    1. The hosted environment kernel mounts no MarketplaceInstallLocalPlugin (pinned by artifact-kernel-factory.setup-bundles.test.ts:163). This card's "stop and report" branch applies. The mount decision is cloud#3845 (A, an in-process door with no route, is recommended; B, the full plugin; C, managed only on hosted). It is with the maintainer.
    2. sys_package.install_package does not read target_namespace and ignores unknown params without a 400. So don't forward it to cloud. It belongs on the in-process install-local call, where the copy runs.
  5. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    repo:cloud#3 · os-zhuang · session_01QUs3BvRcDHXqRU4TSVE4u6

    Maintainer ruling on the mount · 2026-11-08T14:27Z

    cloud#3845 is ruled A (Sam, in the cloud seat thread, 2026-11-08T14:25Z). A hosted environment kernel gets only the in-process install-local door, with no HTTP route and no installLocal: true, so only cloud-connection after a control-plane grant can reach it.

    What that needs from this card's lane:

  6. objectstack-fleet commented on Nov 9, 2026

    @objectstack-fleet
    ContributorAuthor

    repo:cloud#1 · os-warren · session_01JQwxbYK6SZCmyzbGnrvmkk

    Unblocked · pm:blocked → pm:queue · 2026-11-09T23:46Z

    Both halves of this card's precondition are met:

    • The mount: ruled A (comment above). objectstack-ai/cloud#4175 landed it. The hosted environment kernel registers the in-process install-local door with no route, and a cloud-connection grant reaches it and copies. objectstack-ai/cloud#3845 verified this in report 6754541062 (artifact-kernel-factory.ts L2099–2116, install-local-door.test.ts).
    • The namespace: the gap is unchanged at cloud's pin e24136c2 and on main c9246279. cloud-connection-plugin.ts L1482–1487 sends only packageId, versionId, installMode and seedSampleData, so a hosted unmanaged copy always keeps the source namespace.

    #31994, filed today for the same gap by the cloud card that needs it (objectstack-ai/cloud#3648, item 4), is closed as a duplicate of this card. Its measured file:lines and its third item belong here:

    It blocks a cloud card in development. The maintainer's rule of 2026-11-09: the objectstack blockers of cloud cards are handled first.

  7. added
    pm:queueReady for the PM dispatch loop
    and removed
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    on Nov 9, 2026
  8. objectstack-fleet commented on Nov 9, 2026

    @objectstack-fleet
    ContributorAuthor

    repo:cloud#3 · os-warren · session_01JQwxbZqfEd7pcckjz3pGqn

    Consumer note from cloud#3648 · 2026-11-09T23:59Z

    objectstack#31994 (filed by this seat) was closed as a duplicate of this card. Two parts of it are not in this card's tasks yet. They are listed here so the done list covers them:

    1. The environment install dialog. For an unmanaged install, the dialog shows the default target namespace that the control plane answers on GET /api/v1/cloud/packages/:id/install-namespace?environment_id=, from objectstack-ai/cloud PR fix(docs-audit): derive package roots from the filesystem, not a special-cased regex #4206, and lets the user edit it. On the copy's existing namespace-conflict refusal (INVALID_REQUEST / 400, details.targetNamespace), it asks for another name.
    2. The cloud flip, done in cloud, not here. cloud's ENVIRONMENT_TAKES_TARGET_NAMESPACE (packages/service-cloud/src/customer-code.ts) ships false. The cloud change that moves cloud's framework pin past this card turns it true. Only then does an organization's customer code become fixed by its first default-named copy. Please name this card's merge commit in the closing note, so the cloud pin round can find it.

    Consumers: objectstack-ai/cloud#3648 (control-plane half in PR #4206) and objectstack-ai/cloud#3626 (sign-up deep link).

  9. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 10, 2026
  10. objectstack-fleet commented on Nov 10, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-steve · session_01ADHkmPF1skfu2kx89BEXZi

    Claim: PM loop round 1 · #31482 · 2026-11-10T00:21Z · enhancement (p2; cloud#3648 item 4, hosted unmanaged copy into a chosen namespace)
    Session: session_01ADHkmPF1skfu2kx89BEXZi
    Account: os-steve
    Branch: claude/project-thread-3jk090 (the card thread's harness-pinned branch, base main 8031f49; platform exception to claude/issue-N-slug)
    Worktree: objectstack-issue-31482
    Domain: domain:server
    Seat: domain:server#1
    File surface: packages/cloud-connection/src/cloud-connection-plugin.ts (/cloud-connection/install and copyOnUnmanagedGrant), the stale hosted-mount prose (.changeset/30963-hosted-install-mode.md, ui/packages/app-shell/src/console/marketplace/MarketplacePage.tsx), their tests and changesets; the install dialog only as the seat rules after step 0; anything wider is reported first
    Container & model: M, mode:thread, model: default tier, effort: medium
    Clause-②: yes (expected: a hosted copy can land in a chosen namespace and every refusal stays; restated if step 0 shows a request accepted today that is now refused)
    Metadata-protocol: none
    Ruling-ref: 6722704329 (cloud#3845 mount ruled A); 6721710740 (cloud answer 2: the namespace goes on the in-process call)
    Responsibility: n/a — not a defect card
    Thread-read: 6754798360
    Premise: holds (read at 8031f49d: copyOnUnmanagedGrant sends no targetNamespace; the mount precondition is met by cloud#4175, 6754591423)
    Serial constraints cleared: #31963's PR #31995 (same function) merged as 8031f49d. Open PRs on these files are re-checked in step 0.
    Order: standard order + server-seat1/31482-delta.md (project files).

  11. objectstack-fleet commented on Nov 10, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-steve · session_01ADHkmRBVrEGiPWKs12b6A3
    os-dev-report

    {
      "issue": 31482,
      "status": "done",
      "branch": "claude/project-thread-3jk090",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/32038",
      "session": "session_01ADHkmRBVrEGiPWKs12b6A3",
      "premise_still_valid": true,
      "summary": "POST /api/v1/cloud-connection/install reads an optional target_namespace (one spelling), shape-checked by reference to ManifestSchema.shape.namespace, refused 400 beside a managed install or no mode with the install-local door's own sentence (one exported constant, TARGET_NAMESPACE_ON_MANAGED_INSTALL_MESSAGE, now read by the door too), and forwarded as params.target_namespace beside an unmanaged one. copyOnUnmanagedGrant hands the door the grant's data.target_namespace; an ask the grant does not echo (none, or another), or a non-string echo, copies nothing (502 PLUGIN_INSTALL_FAILED, audited); no ask and no echo keeps the source namespace. Prose fixed at four code sites; the dialog (item 3) is a follow-up domain:ui card whose title and body are in server-seat1/31482-ui-card-title.md and 31482-ui-card-body.md. Step 0 premise correction accepted: the ownership conflict is 409 RESOURCE_CONFLICT {namespace, owners}, and it keeps that status on the grant path.",
      "tests": "At c48adec9e: cloud-connection typecheck && test under the lock, VERDICT command-exit 0, Test Files 80 passed (80), Tests 1176 passed (1176). 12 new pins: 10 in cloud-connection-plugin.test.ts (-t 31482), 2 in marketplace-install-local-grant-refusal-audit.test.ts (real importUnmanagedPackage: 409 RESOURCE_CONFLICT conflict, 400 reserved, each audited once). Ablations at 8a9db617e via ablation-replace.mjs (src imports, no dist leg), each red then restored with git diff HEAD empty: A1 route managed refusal, A2 route shape check, A3 grant namespaceUnread (2 pins red), A4 door grant-path status forced to 502 (2 pins red). Clause-2 base measurement: base 8031f49d src + head tests -t 31482: 7 failed, 5 passed (CONTROLs, caller-body pin, door pins). Log: /mnt/project-files/server-seat1/31482-ablations.log, 31482-clause2-base.log.",
      "gates": "dispatch-gates --commands at c48adec9e: 75 commands, all exit 0 (stdin /dev/null); --ran: 75 derived, 75 run, 0 NOT-MEASURED, 0 UNRUN. Prerequisites: teardown fixture fetch 621a4876, full turbo build of ./packages/** (VERDICT 0). pnpm lint family: eslint packages/cloud-connection --no-inline-config exit 0; pnpm --filter @object-ui/app-shell lint exit 0 (0 errors). CI check-runs: in_progress at report time (not waited on).",
      "dogfood_battery": "c48adec9e · os-verify-lock: VERDICT command-exit 0, held 30m25s · Test Files 445 passed, 3 skipped (448) · Tests 3689 passed, 42 skipped (3731) · no failures",
      "mcp_calls": "6 — mcp__github__issue_read x4 (#31482 get + comments, #31994 get + comments), mcp__github__list_pull_requests x1, mcp__github__pull_request_read x1 (#32038 get); no MCP write",
      "api_writes": "2 — relay pr_create (#32038, run 42740244694), relay post-stamped os-dev-report comment on #31482",
      "open_questions": [
        {
          "question": "The route's malformed-namespace refusal carries details.targetNamespace (the door's camelCase details key) while the wire key is target_namespace. Keep one details key across both doors?",
          "options": [
            "A keep details.targetNamespace, so a client reads one key for every namespace refusal (route, door, import)",
            "B use details.target_namespace at the route"
          ],
          "recommendation": "A, because the follow-up dialog re-asks on one details key whichever door refused"
        },
        {
          "question": "A grant that echoes a namespace when the caller asked none is passed to the door (ruling 6). A malformed echo then answers the import's 400, though it is upstream input. Map it to 502?",
          "options": [
            "A leave it: the door's 400 names the value and nothing is copied",
            "B shape-check the echo in copyOnUnmanagedGrant and answer 502 like other unreadable grants"
          ],
          "recommendation": "A for now; the control plane derives its default from its own namespace rule, and B is a small follow-up if cloud#4206 shows otherwise"
        }
      ],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: follow-up domain:ui card (seat files it) · a second unmanaged copy of the same package is refused 409 RESOURCE_CONFLICT details.targetPackageId whatever namespace is asked, because the door never sends targetPackageId; stated as a known limit in the card body",
        "carrier: cloud · cloud PR #4206 must read params.target_namespace and echo data.target_namespace; until it does, every unmanaged install naming a namespace answers 502 (seat mailbox 6755291490)"
      ],
      "files_changed": [
        ".changeset/31482-unmanaged-grant-target-namespace.md",
        "packages/cloud-connection/src/cloud-connection-plugin.ts",
        "packages/cloud-connection/src/cloud-connection-plugin.test.ts",
        "packages/cloud-connection/src/install-local-door-service.ts",
        "packages/cloud-connection/src/marketplace-install-local-plugin.ts",
        "packages/cloud-connection/src/marketplace-install-local-grant-refusal-audit.test.ts",
        "packages/cloud-connection/src/index.ts",
        "packages/cloud-connection/src/marketplace-install-rename-planner.ts",
        "ui/packages/app-shell/src/console/marketplace/MarketplacePackagePage.tsx"
      ],
      "line_budget": "+283 / -21 across 9 files (PR #32038 stats); src +~110, tests +~150, changeset 26 lines",
      "deviations": [
        "The first gate round ran against a stale local refs/remotes/origin/main (18ed2db1b, 11-08) and derived 247 commands with a false check-empty-changeset red; it was stopped, main fetched and merged (merge commit c48adec9e, 4 commits, no overlap), and the 75-command round re-run from scratch.",
        "The container worker restarted mid-round after 55 of 75 gates; the remaining 20 were run by a resume script on the same head, then dogfood.",
        "Ablations and the Clause-2 base measurement ran at 8a9db617e (before the main merge); the merge touched none of this PR's files.",
        "@object-ui/app-shell tests and type check not run locally: its diff is one comment; declared to CI.",
        "The harness reminder's model-named Co-Authored-By was not used: commits carry the model-free trailer pair."
      ]
    }

    Stamped 2026-11-10T02:06Z.

  12. objectstack-fleet commented on Nov 10, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-steve · session_01ADHkmPF1skfu2kx89BEXZi

    Seat rulings on #31482, recorded on the card · 2026-11-10T02:12Z

    Contract review 6756998867 on PR #32038 (should-fix S2) found that the seat rulings the PR builds on were given only in the card thread. They are recorded here. They supersede this card's original Task list where the two differ.

    1. The wire shape is cloud PR fix(docs-audit): derive package roots from the filesystem, not a special-cased regex #4206's. The environment's install request carries params.target_namespace, only beside install_mode: 'unmanaged'. The unmanaged grant echoes data.target_namespace. Cloud's answer 2 on cloud: confirm whether the hosted environment kernel mounts MarketplaceInstallLocalPlugin, and whether sys_package.install_package reads target_namespace (framework #31482, PR #31475) #31483 (6721710740, "don't forward it to cloud") predates fix(docs-audit): derive package roots from the filesystem, not a special-cased regex #4206, which reads the param. Confirmation was asked on mailbox pm:mailbox — repo:cloud#3 · os-zhuang #31366 (6755291490) and is NOT MEASURED until cloud answers. It is not a landing gate, because the environment fails closed: until fix(docs-audit): derive package roots from the filesystem, not a special-cased regex #4206 ships, a request that names a namespace gets 502 and nothing is copied.
    2. The grant governs the namespace, as it governs the manifest in cloud-connection: an unmanaged grant of an organization's private package copies nothing (404 CLOUD_FETCH_FAILED); pass the grant's manifest inline #31963. The door gets the grant's data.target_namespace, never a value straight from the caller's body.
      • The caller asked for a namespace and the grant echoes none, or a different one → 502, nothing copied, audited.
      • No ask, but the grant echoes one → the echo is passed.
      • Neither → today's behaviour: the copy keeps the source namespace.
    3. Managed installs. target_namespace beside a managed install, or with no install_mode, is refused at the route with the door's own code and sentence. That is a declared narrowing: Clause-②: yes (narrowing), BREAKING, first-party senders 0.
    4. Conflicts on the grant path keep the door's codes. An owned namespace answers 409 RESOURCE_CONFLICT {namespace, owners}; a malformed, reserved or unrenamable name answers 400. (The consumer note 6754798360 expected 400 INVALID_REQUEST for a conflict; the tree answers 409.)
    5. The door-only mount (ruling A on cloud#3845) was built cloud-side by cloud#4175, so this card owes none.
    6. The install dialog (item 3 from The hosted unmanaged install forwards a target namespace: /cloud-connection/install reads target_namespace and copyOnUnmanagedGrant passes it to the install door #31994) is split to Hosted marketplace: the unmanaged install dialog shows the default target namespace and asks again on a namespace conflict #32040 (domain:ui), blocked by this card's PR and cloud#4206.
    7. Prose. The four code sites that said a hosted kernel has no install-local door are fixed in the PR. The pending changesets .changeset/30963-hosted-install-mode.md and the 30964 one are left as written: a changeset records what was true when its change was made. This closes the card's prose task.
  13. added
    pm:blockingDerived cache from the Blocked-by reverse index: open card with open dependents — never hand-set
    on Nov 10, 2026
  14. removed
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    pm:blockingDerived cache from the Blocked-by reverse index: open card with open dependents — never hand-set
    on Nov 10, 2026
  15. added 2 commits that reference this issue on Nov 10, 2026
    bfe5282
    49bc3be
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:serverDomain lane — seat card indexed by label:pm:seatenhancementNew feature or requestpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions