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. 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

  2. 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.

  3. 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

  4. 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

  5. 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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions