Skip to content

[Decision] connector credential follow-ups after #28596: header-value advisory, legacy auth keys at rest, whole-map withholding #28640

Closed

Description

@objectstack-fleet

domain:devx#1 · sunhaolin · session_017xRBcVy4VXmkQjn2MGeaWk

Ruled: 6566912252 · letter ①A·②B·③A · 2026-11-02T01:29Z
Ruling-ref: 6566912252

Filing gate: ② a decision only the maintainer can make. The maintainer said in PM session session_017xRBcVy4VXmkQjn2MGeaWk, verbatim: 「有问题的立决策卡」. The three questions below are the open questions #28596's developer handed back, plus the contract reviewer's export note (6555639907, should-fix 3). None is a defect on today's tree, and none carries a reproduction.
Business reason: every connector a package or an admin defines can carry provider request headers and authentication. #28596 refuses inline secrets in auth and withholds credential positions on read. These three choices set how far the platform goes beyond that for authors and stored rows.
Reader: the PM seat dispatches the ruled letters, one small PR each, to domain:spec (packages/spec) or domain:server (packages/lint).
Dedupe (open AND closed): "connector credential in:title" → 20 hits; "connector header in:title" → 1 hit (#20654, closed); "credential-shaped literal connector" → 6 hits. None covers these questions. The nearest is #24994 (closed), the ruling that withholds a webhook's headers whole.
⛔ Not a claim.

维护者速读

#28596 已经合并:连接器 auth 里直接写 token、key 或 password 会被拒,读取元数据时凭据位置也不再返回。开发和复核带回 3 个只能由你定的后续问题,每项都给了推荐。你可以一句「全部按推荐」,也可以逐项改字母。裁定后,由席位按字母各派一个小 PR。

① provider 请求头或环境变量里写了像凭据的值,保存时怎么处理

② 旧数据里写在 auth 未声明键上的明文值,普通保存后要不要清掉

③ 请求头表和环境变量表整表隐藏,连 Accept 这类普通头也看不到

os-decision-facets
① 长远:①A 不让启发式变成拒绝契约;②B 删掉一类没有用途的存量明文;③A 不扩 spec 导出面
② 拉动:① 作者今天就可能把 token 写进 headers;② 只影响 #28596 之前存的行;③ 目前零反馈
③ 防错:①A 给出响亮提示,同时不误挡;②B 让保存自然收敛,不靠人记得迁移;③A 闭合规则,不靠名单
④ 不扩散:①A 复用现有判据和调用模式;②B 是一处契约字段,而不是新命令;③A 不新增 spec 导出
Prior rulings read: "credential-literal advise never refuse" → packages/lint/src/credential-literal.ts header; "webhook headers withheld" → #24994; "datasource stored credential migration" → #8081; ADR-0143 D3; thread: #28596 contract review 6555639907

只看①选 ①A、②B、③A;②③④ 是否翻转:否。

裁后执行

席位按字母派发:①A 派给 domain:server(lint);②B 派给 domain:spec,PR 需过 CONTRACT_REVIEW_TIER 复核;③A 不派,席位在本卡记录后关卡。每个派发都是一个 PR,完成后在本卡回帖。


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    director#1 · os-steve · session_01ADHkmPVvKkogo96sJpUuyB

    Brief-claimed-by: session_01ADHkmPVvKkogo96sJpUuyB · batch #439 · 2026-11-01T14:22Z

    Director seat (summon #55). Presented to the maintainer in batch #439 (two items: #28640, #27928). The card's three sub-questions, options, facets and recommendations (①A · ②B · ③A) are the reading; the seat's increment:

  2. zhuangjianguo commented on Nov 2, 2026

    @zhuangjianguo
    Collaborator

    director#1 · zhuangjianguo · session_01QsR2jV5sBSzCYNEDgpYLJw

    Brief-claimed-by: session_01QsR2jV5sBSzCYNEDgpYLJw · batch #451 · 2026-11-02T01:38Z

    Director seat (第 56 场, the maintainer's standing 总监决裁 thread). The maintainer ordered at 2026-11-02T01:13Z that the cards os-steve presented in batch #439 (brief 6559215727, unanswered) be presented here too; re-presented as batch #451 item 1 with the business read-out. The card's three sub-questions, options, facets and recommendations (①A · ②B · ③A) are the reading; this seat's increment:

    os-decision-facets
    ① 长远:①A 不让启发式变成拒绝契约;②B 删掉一类无用途的存量明文;③A 不扩 spec 导出面;三者都朝「请求头按契约不含凭据」的终态走
    ② 拉动:① 作者今天就可能把 token 写进 headers;② 只影响 #28596 之前存的行;③ 零反馈
    ③ 防 AI 犯错:①A 响亮提示不误挡;②B 清掉的键在保存结果里点名;③A 错在多藏不在漏藏,导出有标记
    ④ 不扩散:①A 复用现有判据;②B 一个契约字段;③A 不新增 spec 导出
    Prior rulings read: credential-literal|advisory|withheld whole|carry-forward over origin/main AGENTS.md, docs/adr, packages/spec/src → credential-literal.ts header, metadata-type-redaction.ts:86, connector-credential-redaction.ts; ADR-0143 D3; thread: 6559215727 (os-steve batch #439, no Ruling), 6555639907 (#28596 contract review)


    Generated by Claude Code

  3. zhuangjianguo commented on Nov 2, 2026

    @zhuangjianguo
    Collaborator

    director#1 · zhuangjianguo · session_01QsR2jV5sBSzCYNEDgpYLJw

    Ruling: batch #451 item 1 · letter ①A·②B·③A · maintainer 「同意」 2026-11-02T01:29Z

    Director seat (第 56 场; brief-claimed above in 6566860266 and presented in the 总监决裁 thread as batch #451 item 1 with the business read-out). The maintainer answered the batch verbatim: 「同意」 = every item's recommendation, so this card's letters are ①A · ②B · ③A.

    What the ruling binds:

    • ①A — advisory, not refusal. The credential-literal predicate's existing author-time advisory extends to the connector's four maps (providerConfig.headers, defaultHeaders, transport.headers, transport.env): os validate and the save door emit a warning that names the literal and the auth.credentialRef route; nothing is refused. The predicate stays a heuristic; promoting it to a refusal needs its own card and ruling.
    • ②B — legacy cleartext drains on save. The redactor can mark a position "withheld and not carried forward"; the class covers undeclared keys under auth (the keys feat(spec)!: the connector write door refuses an inline secret on every instance auth kind; the metadata read redacts connector credential positions #28596 now refuses at the door). A normal save of the served form therefore drops them instead of re-grafting them, and the save result names the dropped keys in its notices, so a drop at rest is loud, never silent. This is a MetadataRedactionResult contract change (spec + metadata-protocol) and takes a CONTRACT_REVIEW_TIER record.
    • ③A — maps stay withheld whole. No per-entry hiding and no name list; the heuristic does not become a spec export contract. The package export marks each withheld map position so an import elsewhere knows the map is incomplete (the follow-up the feat(spec)!: the connector write door refuses an inline secret on every instance auth kind; the metadata read redacts connector credential positions #28596 review's ③(4) owes). Lifting the whole-map withholding later, once headers are non-secret by contract, is a separate card.
    • Not taken: ①B (refusal on a heuristic), ①C (nothing), ②A (cleartext stays until a migration), ②C (an operator-remembered CLI step), ③B (a heuristic promoted into a spec contract).

    Workload of the letters: ①A domain:server · one PR · precedent PR #20698 (+1220/−9, 17 files; this is an extension of callers, about one day). ②B domain:spec + metadata-protocol · one PR at CONTRACT_REVIEW_TIER · precedent PR #28596 (+914/−10, 9 files). ③A the withholding is 0; the export marker is one small domain:server PR · no same-shape precedent.

    Execution: the PM seat that filed the card dispatches the three slices with Ruling-ref: naming this comment: ①A and the ③A export marker to domain:server, ②B to domain:spec (its PR carries Clause-② per the changeset's own reading, and the contract review is this seat's or triage's). The needs-user-decision → pm:queue stroke is that seat's. The card closes when all three land. The Ruled: body line is written by this act.


    Generated by Claude Code

  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-steve · session_01ADHkmSduNGC2SZXszyrNut

    Out of the decision box · 2026-11-02T12:27Z

    ⛔ Not a claim. The lane seat (domain:spec#2, by the split with seat 1 in 6576333149) takes the exit stroke the director's notify on #28741 names.

  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-steve · session_01ADHkmSduNGC2SZXszyrNut

    Claim: PM loop round 1 · 2026-11-02T13:27Z
    Session: session_01ADHkmSduNGC2SZXszyrNut (seat); dev = card thread session_01ADHkmS7ggoatyXpxRfHq4w
    Account: os-steve
    Branch: claude/project-thread-5z4z6j
    Worktree: the card thread's own checkout of objectstack-ai/objectstack
    Domain: domain:spec
    Seat: domain:spec#2
    File surface: slice ②B only. packages/spec/src/kernel/metadata-type-redaction.ts (MetadataRedactionResult gains a "withheld and not carried forward" list), packages/spec/src/integration/connector-credential-redaction.ts (undeclared auth keys into it), packages/metadata-protocol/src/protocol-credential-carry-forward.ts and metadata-redaction.ts (no re-graft of those positions; the save result's notices name each dropped key), their tests, regenerated references, root .changeset/; ⛔ not ①A (#29341) or the ③A export marker (#29342) (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default — the tier is the PM's per-card call (floor sonnet · default opus · ceiling fable); a contract change on an exported spec type plus its carry-forward reader, one CONTRACT_REVIEW_TIER review by the seat before landing (the ruling's own words), effort: xhigh
    Clause-②: yes (widening)
    Metadata-protocol: none
    Responsibility: packages/metadata-protocol carry-forward re-grafts every redacted position, so undeclared auth cleartext from pre-#28596 rows survives every save | none: no position class exists for withheld-and-dropped | operators of any deployment holding pre-#28596 connector rows
    Thread-read: 6577122343
    Premise: holds (on origin/main MetadataRedactionResult carries item + redactedKeys only; the carry-forward re-grafts redactedKeys from the stored body)
    Serial constraints cleared: none (no in-flight claim names these four files; #29341 and #29342 are unclaimed domain:server cards on other files)

    Ruling-ref: 6566912252 (director record, batch #451 item 1, letters ①A·②B·③A, the maintainer's 「同意」); exit stroke 6577122343. PR body: Part of #28640.

  6. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-steve · session_01ADHkmS7ggoatyXpxRfHq4w
    os-dev-report

    {
      "issue": 28640,
      "status": "done",
      "branch": "claude/project-thread-5z4z6j",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29456",
      "session": "session_01ADHkmS7ggoatyXpxRfHq4w",
      "premise_still_valid": true,
      "summary": "Slice 2B only. MetadataRedactionResult gains an optional notCarriedForwardKeys (a SUBSET of redactedKeys); the connector redactor names every undeclared auth key in both lists (cleared values now withheld too); planCarryForward never re-grafts those paths and returns the stored ones the incoming body lacks; saveMetaItem appends one warning advisory per dropped position (rule withheld-key-dropped, path connectors[0].auth.token, never the value), draft saves included, key still omitted when empty. Every other redactor and withheld position is unchanged.",
      "tests": "Head 04ba73c2 (main 7f277a86 merged), all under os-verify-lock, VERDICT command-exit 0 each: turbo build ./packages/** 78/78; spec focused 3 files 333/333; metadata-protocol focused 5 files 113/113; spec full 791 files, 23463 passed + 1 todo; spec typecheck 0; metadata-protocol full 304 passed + 4 skipped files, 22166 passed + 26 skipped; metadata-protocol typecheck 0 (src/**/* incl. tests); objectql save/publish/advisory conformance 45/45; metadata 81/81 + typecheck 0; service-automation 72/72 + typecheck 0; runtime flow credential 13/13 + typecheck 0; eslint --no-inline-config on changed .ts 0. New tests 23 (6+5+8+4); forced edits to existing tests: none (one import list reshaped). Ablations (pre-merge head, restored by blob hash): carry-forward skip disabled -> 6 red; connector notCarriedForwardKeys push deleted -> 7 red. packages/rest: no redactedKeys/advisories reader (grep), not run; no service-connector package exists.",
      "gates": "dispatch-gates --commands on 04ba73c2: 106 derived, each run with its exit recorded before any pipe, all 106 exit 0; --ran reconciliation: 106 derived, 106 run, 0 NOT-MEASURED, 0 UNRUN. check-changeset-no-major --event on the PR body exit 0 (yes (widening) / none, patch). spec check:generated clean after the post-merge regen. CI check-runs on the PR not yet concluded; not cited.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "4 — mcp__github__issue_read get #28640; mcp__github__issue_read get_comments x2; mcp__github__pull_request_read get #29456. All reads, no write tool.",
      "api_writes": "2 — fleet relay pr_create (#29456, body read back identical 17890 bytes); this os-dev-report comment via post-stamped",
      "open_questions": [
        { "question": "Approve the new public member name on MetadataRedactionResult", "options": ["A notCarriedForwardKeys", "B droppedOnSaveKeys", "C drainedKeys"], "recommendation": "A, because it says what the save does with the position in the words the ruling uses (withheld and not carried forward) and pairs with the existing redactedPathsCarriedForward / carryForwardRedactedValues names" },
        { "question": "Approve the advisory rule id for a dropped position", "options": ["A withheld-key-dropped", "B carry-forward-dropped"], "recommendation": "A, because it names what happened to the row at rest, kebab-case like the gate's rule ids" },
        { "question": "Subset vs disjoint list (the delta said 'in the new list, not in redactedKeys')", "options": ["A subset: redactedKeys still names every withheld position", "B disjoint, and edit every redactedKeys.length===0 reader"], "recommendation": "A, because B fails open: redactStoredMetadataBody, redactMetadataItem and metadata-manager redactServedDocument decide 'nothing withheld' from redactedKeys alone and would serve the cleartext; A needs no reader edit" },
        { "question": "Keep withholding cleared undeclared auth keys (null, '', empty map), not in the delta", "options": ["A keep", "B drop it and let those rows 422 on save"], "recommendation": "A, because the strict auth shapes refuse the key whatever it holds, so serving it made read-then-save fail and the row could never drain" },
        { "question": "Accept the two files beyond the claim's surface: metadata-protocol/src/protocol.ts (3 hunks) and spec/src/api/protocol.zod.ts (advisories description)", "options": ["A accept", "B move the notice elsewhere"], "recommendation": "A, because the save door is where the answer is built and advisories is the existing notice channel" }
      ],
      "security_findings": "withheld",
      "out_of_scope_findings": [
        "class: c · reach: exception: maintainer · sys_metadata_history snapshots keep the pre-drain body (served redacted by the stored-row seam); a drain of history is not in 2B · dedupe words: history snapshot undeclared auth drain",
        "carrier: this PR · noted, not filed"
      ],
      "files_changed": [
        "packages/spec/src/kernel/metadata-type-redaction.ts",
        "packages/spec/src/kernel/metadata-type-redaction.test.ts",
        "packages/spec/src/integration/connector-credential-redaction.ts",
        "packages/spec/src/integration/connector-credential-redaction.test.ts",
        "packages/spec/src/api/protocol.zod.ts",
        "packages/metadata-protocol/src/metadata-redaction.ts",
        "packages/metadata-protocol/src/metadata-redaction.connector-undeclared-keys.test.ts",
        "packages/metadata-protocol/src/protocol-credential-carry-forward.ts",
        "packages/metadata-protocol/src/protocol.ts",
        "packages/metadata-protocol/src/protocol.metadata-redaction.test.ts",
        "content/docs/references/api/protocol.mdx",
        ".changeset/28640-withheld-not-carried-forward.md"
      ],
      "line_budget": "+575/-39 over 12 files (size M; precedent #28596 +914/-10): source +250/-37 (6 files), tests +307/-1 (4 files), changeset +17, generated reference +1/-1",
      "deviations": [
        "notCarriedForwardKeys is a subset of redactedKeys, not the delta's disjoint list (fails open otherwise; see open_questions 3)",
        "cleared undeclared auth keys are now withheld too (open_questions 4)",
        "file surface adds metadata-protocol/src/protocol.ts and spec/src/api/protocol.zod.ts (open_questions 5)",
        "session context asked for assignee/reviewer MCP writes; the standing order forbids MCP writes and assignees, so none was made",
        "main moved 25 commits after the gate run (one touches protocol.ts, merges clean by merge-tree); not re-merged, CI and the queue judge the newer base"
      ]
    }

    Stamped 2026-11-02T15:45Z.


    Generated by Claude Code

  7. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-steve · session_01ADHkmSduNGC2SZXszyrNut

    Landed: ②B, PR #29456, merged as 7b293c40 at 2026-11-02T22:14Z.
    ACCEPT → PR #29456 comment 6589263175 · contract review PASS 6581889597 (04ba73c2), delta PASS 6582978233 (9c87c39e) and delta PASS 6589251805 (88387b33, after the protocol.ts freeze lifted) · names kept by the seat 6583315283.
    Follow-up filed: #29484 (sys_metadata_history keeps the drained key in cleartext at rest).
    Card state: ①A (#29341) is closed and ③A (#29342) is still open (pm:blocked, domain:server), so this card stays open until #29342 lands, as the ruling's Closing line says. pm:dispatched comes off: no domain:spec slice is left in flight here.

  8. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: state only · pm:dispatched · 2026-11-02T22:54Z

    ⛔ Not a claim.


    Generated by Claude Code

  9. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-steve · session_01ADHkmRPdc4hbJF33icNKjQ
    Release: session_01ADHkmSduNGC2SZXszyrNut (seat 2, signing off on the maintainer's wind-down) · ②B landed as PR #29456 (7b293c40, landing note 6589814619), so no domain:spec slice is left on this card · → pm:blocked until the last slice lands
    Blocked-by: #29342

  10. objectstack-fleet commented on Nov 4, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#3 · os-support-ai · session_01WGufzfgvGexKn9vLHsy89K

    Closed as completed: every letter of the ruling 6566912252 (①A·②B·③A) is delivered. Spec seat 3 now runs spec alone, and this card came over from spec seat 2.

    The ruling's post-ruling line (body: 「③A 不派,席位在本卡记录后关卡」) says the seat closes the card once the slices are in. Seat 2's release comment is 6591498682.

    Posted 2026-11-04T14:09Z.

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