You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
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
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/maincd065d36) 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.
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.
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.
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"
]
}
Activity
objectstack-fleet commentedon Nov 1, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: 发布并装进一个环境 | none | P④
Triage: p2 ·
domain:server·area:automation·pm:epickept · 2026-11-01T07:53Z⛔ Not a claim.
providerConfigfile ref is read from the HOST's package root, so an install-local app can bind the host's own file (measured: it materializedreadywith the host's OpenAPI document) #28534 class, found by PR fix(service-automation,objectql,cloud-connection)!: an installed package's connector entry never reads the host's files #28587's boundary review.providerConfigfile ref is read from the HOST's package root, so an install-local app can bind the host's own file (measured: it materializedreadywith the host's OpenAPI document) #28534 and connector apps: an installed app's package-relativeproviderConfig.specfile is not in its built artifact, and the loader resolves it against the host's own package root, so an OpenAPI connector app installed from the marketplace cannot read its spec #28505.pm:epicstays. The epic PM of [Epic] Marketplace and connector auto-shelf — E1 platform prerequisites (openapi/mcp hardening, outbound OAuth, request signing), E2 administrator credential hand-off, E3 author recipes and handbook, E4 the first shelf of official connector apps #27293 dispatches it together with the rest of that class.Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
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:queuein this act; thedomain:*label stays. This card waited for PR #28587 (#28534), which merged asd2c487407, so it builds on the classifier onmain. The card stays a sub-issue of #27293 for tracking only, and the epic seat no longer reserves it. The triage grade stands.objectstack-fleet commentedon Nov 1, 2026
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 issession_01FEkQ5mBUwWJMnLUdKBYraTAccount:
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:serverSeat:
domain:server#2Ruling-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; changesetsContainer & model:
M,mode:thread,model: opus(--tiernames no path mandate: PM's call, default),effort: highClause-②: 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_validSerial constraints cleared: PR #28587 merged (
d2c487407); PR #28639 merged (6b9c1ca99); no open PR on the materializer at claim time (the dev re-reads beforepr_create)Resume-from: none — fresh from
origin/mainState: →
pm:dispatched, assigned toos-project-manager, recorded by this claim.Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
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
fix(service-automation): a stored connector entry refused its package…
objectstack-fleet commentedon Nov 1, 2026
domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo
Landing record · #28594 · PR #28671
domain:serverseat 2 ·session_0186vfjHHMsRXC9EUT9hTFMo· 2026-11-01T14:45Z15e83114git merge-base --is-ancestor 15e83114 origin/maingit ls-remote origin refs/heads/gh-readonly-queue/*matching 28671git grep -c stored origin/main -- packages/qa/dogfood/test/stored-connector-package-ref-restart.dogfood.test.tsauthoredprovider-bound connector row resolves its package-relativeproviderConfigrefs against the HOST's root (the #28534 class, through the metadata door) #28594):providerConfigfile ref is read from the HOST's package root, so an install-local app can bind the host's own file (measured: it materializedreadywith the host's OpenAPI document) #28534's message. Only entries the host stack declares read the host's files.6559191364.providerConfigfile ref is read from the HOST's package root, so an install-local app can bind the host's own file (measured: it materializedreadywith the host's OpenAPI document) #28534's installed and unrecorded refusals._packageIdwhere the column records another package or none (#28594 follow-up) #28673 (the by-name, draft and hydration reads; seat 1) and service-automation: a stored connector row whose configuration became invalid stops the next boot, where the same fault after boot only skips the row (#28594 follow-up) #28698 (other stored-row faults at boot; seat 2).Release: claim
6557460226(session_01FEkQ5mBUwWJMnLUdKBYraT, branchclaude/project-thread-jhlplj) · landed.pm:dispatchedremoved; assignee cleared; the card closed on merge.Generated by Claude Code
test(metadata-protocol): the hydrated flow body's _packageId is the c…