Skip to content

ADR-0025 M2 — cloud fetch + per-plugin permission enforcement: artifact download route, os plugin install <id>@<version>, SecurePluginContext scoped to the granted set (services, hooks), side-by-side versions / yank, delete the enforcement pin #27124

Open

Description

@objectstack-fleet

Part of #27108 (M2). Blocked-by: #27123. Filing gate: ③ maintainer-directed — ruling 6461953053 on objectstack#26553 and ADR-0025 v2 §3.4 / §3.5 / §3.7 / §3.8 (PR #27118, merged). Filed by the director seat (session_01KrKXQVvgYk2AJ4VkqMobyb, ledger objectstack#12708). ⛔ Not a claim. ⛔ No domain:*: spans cloud service-cloud routes and objectstack core / runtime; triage sets the lane(s), likely one cloud card and one server card.

维护者速读

两件事。① 云端取件:云端补 .osplugin blob 下载路由(带发布者签名 + 平台反签),os plugin install <id>@<version> 走 resolve → 兼容检查 → 授权同意 → 下载 → M1 的本地路径;并排多版本与 yank。② 权限真正拦截:按 §3.5 第 7 步给每个插件包一个按授权集收口的 SecurePluginContext,只拦 services 与 hooks(Q4);同一 PR 删掉 granted-permissions-not-enforced.pin.test.ts 和 PluginDisclosure.tsx:148 那句「runtime does not yet restrict」。M2 落地前不装任何第三方插件。

What lands

  1. Cloud download route (cloud/packages/service-cloud/src/routes/marketplace.ts or the artifact route): serve the stored .osplugin blob for artifact_kind: 'plugin' with signature + platform_signature; today GET …/artifact returns the manifest JSON.
  2. os plugin install <id>@<version>: resolve on sys_package_version, protocol-first compatibility (v2 §3.8), the consent step reusing the shipped disclosure + granted_permissions (409 re-consent on widening), download, then the M1 verify → materialize → record → load path. Side-by-side versions with an installation pointer swap; yank on sys_package_version.status.
  3. Per-plugin SecurePluginContext (packages/core/src/security/plugin-permission-enforcer.ts, SecurePluginContext): constructed at §3.5 step 7 for every plugin an artifact carries, scoped to the granted set registered by artifact-granted-permissions.ts; enforceServiceAccess and enforceHookTrigger gate the plugin's PluginContext; denials logged. fs / network classes untouched (M3).
  4. Delete packages/core/src/security/granted-permissions-not-enforced.pin.test.ts, the "NOT ENFORCED: nothing queries that registry" docblock in the enforcer, the "registers the consented set; it does not intercept access" sentence in artifact-granted-permissions.ts, the ADR-0025 §3.7 registration note, and the PluginDisclosure.tsx:148 sentence — in the same PR as (3).
  5. Acceptance: the Stripe sample installs from a cloud registry; a plugin whose granted set omits a service it calls is refused at that call and the denial is on the audit log; the tamper cases of M1 hold over the download path.

Not in M2

  • T1 / T2 tiers, publish-side scans, secret-refs, fs / network enforcement, RLS-scoped grants — M3.

Size: L (cloud route + CLI install · enforcement, two PRs minimum). Clause-②: no. Metadata-protocol: none.

Related

#27108 (epic, Q2, Q4, Q5), ADR-0025 v2 §3.4 / §3.5 / §3.7 / §3.8, ADR-0019 §Out-of-scope (the load-bearing wall), #13457, #27110.

Activity

  1. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Triage: cloud · domain:cloud + status:parked · p1 kept · 2026-10-28T07:59Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. added
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    domain:cloudTouches cloud: the whole card is the cloud PM's (repo:cloud seat); no objectstack lane claims it
    status:parkedParked — exempt from the PM sweep and half-state patrol until its owner migrates it (e.g. cloud PM)
    and removed
    pm:queueReady for the PM dispatch loop
    on Oct 28, 2026
  3. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Frozen (2026-10-28T16:23Z). The maintainer chose 「M1 做完,其余冻结」 on the decision card about #27108 after the bridges ruling. That ruling is recorded on #27108, and the bridges epic is #27314. This card stays parked and is not dispatched. It unfreezes when a paying customer asks for third-party code distribution. ⛔ Not a claim.

  4. added
    pm:queueReady for the PM dispatch loop
    repo:cloudCard routed whole to the cloud PM: needs cloud code, a producer or a fact (cloud owns it to closure)
    and removed
    status:parkedParked — exempt from the PM sweep and half-state patrol until its owner migrates it (e.g. cloud PM)
    on Nov 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratedomain:cloudTouches cloud: the whole card is the cloud PM's (repo:cloud seat); no objectstack lane claims itenhancementNew feature or requestpm:queueReady for the PM dispatch looppriority:p1High: required for production / M2repo:cloudCard routed whole to the cloud PM: needs cloud code, a producer or a fact (cloud owns it to closure)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions