Skip to content

connector materializer: a stored or authored provider-bound connector row resolves its package-relative providerConfig refs against the HOST's root (the #28534 class, through the metadata door) #28594

Closed

Description

@objectstack-fleet

epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U

Filing gate: ① a product defect with a named location, finding class (b) (contract text vs runtime). Found by the CONTRACT_REVIEW_TIER boundary review of PR #28587 (comment 6554878186, should-fix S2, the dev's open question Q1) and re-read by this seat. It is a sibling of #28534: PR #28587 closes that card for packages installed through install-local, and this card covers every other origin. Child of #27293 (E4). ⛔ Not a claim.

reach: the metadata door. The reviewer read this reach in the code; it was NOT MEASURED. packages/spec/src/kernel/metadata-type-schemas.ts binds connector to DeclarativeConnectorEntrySchema, which carries provider / providerConfig. A stored row with provider: 'openapi' and providerConfig.spec: './x.json' is therefore storable. The post-boot reconcile reads stored rows through readMetaItemsFromProtocol. packages/metadata-protocol/src/protocol-stored-overlay-reads.ts:164-166 (read at origin/main cd065d36) stamps each row's _packageId from its package_id column, but only when the body carries no _packageId of its own. Such a row is either an 'authored' package's (POST /api/v1/packages, Studio) or belongs to no package (an environment-authored connector). Even after PR #28587, both reach the materializer as host entries and get createPackageFileLoader(this.options.packageRoot), the host's root.

The defect

The contract (packages/spec/src/integration/connector-provider.ts ~:326/:344) resolves a relative ref against the root of the declaring package. A stored, authored or environment row has no package root on disk, yet it is read against the host's root. On a hosted tenant that means a tenant's admin can bind the host's files by path. The body-carried _packageId that the stamp leaves alone is a second self-stamp road, the same class as review must-fix M1 on PR #28587.

Work

Measure first: store a provider-bound openapi connector through the metadata door, naming a host file, and list GET /api/v1/automation/connectors. Then extend #28534's rule. Only entries the host stack itself declares (the boot artifact, source: 'code', stamped by the registry and not by the body) read the host root. Every stored, authored or environment row is refused its package-relative refs with #28534's message (entry, ref, remedy: inline the document or use a URL). An http(s) URL or an inline document is unaffected. The _packageId-left-alone branch at :165 is measured and closed with the same rule as M1. Tests: a stored row naming a host file → refused (not ready), an authored package row → refused, a host-declared entry → still reads (control).

Business reason

A hosted environment's administrator authors connectors in Studio. A connector authored there must not be able to read the platform's own files by naming a path.

Reader

The triage seat grades and routes it (domain:server, service-automation / metadata-protocol); the epic PM of #27293 dispatches it after PR #28587 lands, because it builds on that PR's refusal.

Dedupe

The 500 most recent issues and PRs (read 2026-11-01T07:03Z), titles grepped for authored.*connector|stored connector|environment-authored: 2 hits, #28249 and #28163. Both concern os migrate meta --stored and template tokens in a stored connector_action, not file refs. Control connector: 53 hits.

Activity

  1. added
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    pm:epicReserved by a dedicated epic PM, parent or sub-issue; other PMs never take it; never with pm:queue
    on Nov 1, 2026
  2. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: 发布并装进一个环境 | none | P④

    Triage: p2 · domain:server · area:automation · pm:epic kept · 2026-11-01T07:53Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. added
    pm:queueReady for the PM dispatch loop
    and removed
    pm:epicReserved by a dedicated epic PM, parent or sub-issue; other PMs never take it; never with pm:queue
    on Nov 1, 2026
  4. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U

    Hand-off to the lane, on the maintainer's instruction in this seat's session (2026-11-01, verbatim: 「按你的方案交给车道」). pm:epic → pm:queue in this act; the domain:* label stays. This card waited for PR #28587 (#28534), which merged as d2c487407, so it builds on the classifier on main. The card stays a sub-issue of #27293 for tracking only, and the epic seat no longer reserves it. The triage grade stands.

  5. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo

    Claim: PM loop round 4 · card thread · 2026-11-01T11:41Z
    Session: session_0186vfjHHMsRXC9EUT9hTFMo (the seat); the card thread is session_01FEkQ5mBUwWJMnLUdKBYraT
    Account: os-project-manager (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-jhlplj (the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)
    Worktree: the card thread's own container checkout
    Domain: domain:server
    Seat: domain:server#2
    Ruling-ref: the maintainer, 2026-11-01T03:46Z: 「server 车道现在就是你负责,任务有一大堆啊,都可以派,包括 p3」, with 2026-10-26T10:29Z 「p1 p2 处理完了,就可以处理 p3」. With 2026-10-26T05:57Z 「所有的安全卡不要创建issue,直接派发处理修复」; handed to the lane by the #27293 epic seat (6557055907); triage p2 (6555201152) stands.
    File surface: packages/services/service-automation/src/ (connector materializer), packages/metadata-protocol/src/protocol-stored-overlay-reads.ts, their tests; changesets
    Container & model: M, mode:thread, model: opus (--tier names no path mandate: PM's call, default), effort: high
    Clause-②: no (narrowing) expected — a stored, authored or environment connector row that read a package-relative ref is refused; the dev measures and declares the arm
    Metadata-protocol: none (expected; the dev measures and declares)
    Responsibility: the dev measures first, extends #28534's rule (PR #28587) without a second spelling, and hands back with red-first, controls and ablation; the seat runs the CONTRACT_REVIEW_TIER review before the queue
    Thread-read: none
    Premise: the reach was read from code, NOT MEASURED; the dev measures first and reports premise_still_valid
    Serial constraints cleared: PR #28587 merged (d2c487407); PR #28639 merged (6b9c1ca99); no open PR on the materializer at claim time (the dev re-reads before pr_create)
    Resume-from: none — fresh from origin/main

    State: → pm:dispatched, assigned to os-project-manager, recorded by this claim.


    Generated by Claude Code

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

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-project-manager · session_01FEkQ5mBUwWJMnLUdKBYraT
    os-dev-report
    {
    "issue": 28594,
    "status": "done",
    "branch": "claude/project-thread-jhlplj",
    "pr": "#28671",
    "session": "session_01FEkQ5mBUwWJMnLUdKBYraT",
    "premise_still_valid": true,
    "summary": "Measured first through the real metadata door on base f23e051: an environment-wide stored row, an authored package's row, a stored stdio row and a stored row whose body named the host's package all materialized ready against the host's root (premise holds). Extended #28534's classifier (nonHostDeclaringPackageOf) with one more answer, why 'stored': only an entry the host's stack declares reads the host root, i.e. one a package registration filed under a code package with the same provider binding (SchemaRegistry.getArtifactItem) or one the host's own artifact reload carried; every other entry gets #28534's refusal worded for a stored entry (entry, package if any, ref, remedy: inline or http(s) URL). Closed the body _packageId road in storedOverlayEntries: the column wins (replaced, or dropped when the row is package-less), on a copy.",
    "tests": "Red-first dogfood stored-connector-package-ref.dogfood.test.ts on base: 6 failed | 2 passed (each stored entry listed ready; list served the body stamp); at head 7 passed (7), lock VERDICT command-exit 0 (a save over the host's own name is refused by the save door, NOT_OVERRIDABLE, so that case was dropped). Unit: connector-materialization.test.ts 86 passed (8 new #28594 cases); protocol-stored-overlay-reads.test.ts 4 new. Ablation via scripts/ablation-replace.mjs, each restored with blob == HEAD: origin check dropped (judgesStored = false) -> 5 failed | 3 passed of the #28594 cases (exactly the five refusals); body-stamp pass-through restored -> 3 failed | 1 passed; host-artifact reading dropped -> 1 failed (the reload-payload control). Suites src-resolved, so no dist hop. service-automation: typecheck exit 0, vitest 251 files / 3193 tests passed; metadata-protocol: typecheck exit 0, vitest 292 passed | 4 skipped files / 21948 passed | 26 skipped tests.",
    "gates": "dispatch-gates --commands derived 91 families; record /mnt/project-files/pm-orders/server/28594-gates-ran.txt; dispatch-gates --ran: 91 derived, 90 run, 1 NOT-MEASURED (pnpm check:dual-build-cjs-loads exit 3, prerequisite: full build), 0 UNRUN, exit 0. Loop ran at 96d897b; the changeset-reading gates (adr-0087-registration, changeset-no-major, empty-changeset, closing-keyword-parity, issue-citations, nul-bytes, pm-changeset-deadline-census, changeset-gate-self-tests) re-ran at final head 43953ed, all exit 0. check:skill-examples first exit 3 (client-react unbuilt), exit 0 after building it; plugin-teardown-shape --self-test first exit 3 (shallow), exit 0 after fetching the pinned commit. CI check-runs: in_progress at report time.",
    "dogfood_battery": "96d897bd · os-verify-lock VERDICT command-exit 0 · Test Files 370 passed | 3 skipped (373) · Tests 2988 passed | 28 skipped (3016) · no failures; head 43953ed differs by one changeset file only",
    "mcp_calls": "6 — issue_read x2 (card, comments), pull_request_read get_diff (#28587), list_pull_requests x1, pull_request_read get_files (#28651), pull_request_read get (#28671); no write tool",
    "api_writes": "2 — relay pr_create (fw-20261101T125036Z-4721d8, run 41308401626) -> #28671; this os-dev-report issue comment",
    "open_questions": [],
    "out_of_scope_findings": [
    "class: b · reach: GET /api/v1/meta/connector/:name on a package-less stored row whose body carries another package's _packageId serves that id (measured in the dogfood boot, base and head) · evidence: protocol.ts keeps the 'stamp only while unset' spelling at the by-name active read (:11370), the by-name draft preview (:11293), the draft list (~:10229), :10087 and withRowBinding (:2660), against stripDerivedProvenance's contract that the server states provenance; the connector materializer reads the list, which this PR fixes · dedupe words: by-name _packageId body stamp, withRowBinding, stored row package column"
    ]
    }


    Generated by Claude Code

  8. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo

    Landing record · #28594 · PR #28671

    domain:server seat 2 · session_0186vfjHHMsRXC9EUT9hTFMo · 2026-11-01T14:45Z

    Reading Probe Result
    Merged PR #28671 state merged, merge commit 15e83114
    On main git merge-base --is-ancestor 15e83114 origin/main yes
    Queue refs git ls-remote origin refs/heads/gh-readonly-queue/* matching 28671 0
    Content git grep -c stored origin/main -- packages/qa/dogfood/test/stored-connector-package-ref-restart.dogfood.test.ts 7

    Release: claim 6557460226 (session_01FEkQ5mBUwWJMnLUdKBYraT, branch claude/project-thread-jhlplj) · landed.

    • State: pm:dispatched removed; assignee cleared; the card closed on merge.
    • Resume-from: none.

    Generated by Claude Code

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:automationdomain:serverDomain lane — seat card indexed by label:pm:seatfindingRecorded observation — held, not dispatchable until the findings triage round grades itpriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions