[Decision] The share-link route probe re-opens the existence oracle that share-link-service deliberately closed — a switched-off link with a password still answers 401 #14637

Description

@os-sales

Filed by the domain:services PM seat (session session_01AUF1NoViznQK32gqpK8wS8) from the non-blocking notes of the in-seat Clause-② contract review of PR #14580 (#14033) — round 1 note 5, adopted verbatim on 14033#issuecomment-5511376156. Re-measured by the triage seat at origin/main2aa8456.

Item 2 of the original filing (the changeset's "burst the log once" wording) is split to #14668 and is dispatchable now — it is not held behind this ruling.

The defect

resolveToken refuses a link whose object has publicSharing.enabled off, and the refusal is the undifferentiated null the #14033 ruling asked for — over HTTP a 404 INVALID_OR_EXPIRED, byte-identical to an unknown token, pinned at share-link-eligibility.test.ts:992-1022.

But the route's probe runs afterresolveToken returns null and answers from the row, with no knowledge of the object's block:

  • packages/plugins/plugin-sharing/src/share-link-routes.ts401 NEEDS_PASSWORD / WRONG_PASSWORD for a row carrying password_hash; 401 SIGN_IN_REQUIRED for audience === 'signed_in' without a signed-in viewer
  • packages/runtime/src/domains/share-links.tsa duplicated twin of the same probe, same arms, same codes

So for those two link shapes an anonymous caller can still tell a real-but-switched-off token from an unknown one, and a correct password on such a link answers WRONG_PASSWORD.

⭐ Why this is more than "pre-existing, out of scope"

The service layer wrote the threat model down, in the same feature, immediately above the arm that closes it:

…for a caller who may hold nothing but a token, a distinguishable "sharing is off for this object" is an existence oracle, so the answer is the one revoked / expired / unknown / ineligible already give (over HTTP the generic 404).

The route above it then re-opens exactly that oracle for two of the three shapes. This is not a gap someone forgot to close — it is a security property that is stated in one layer and defeated in the layer above it, which is strictly worse than never having claimed it, because the next reader believes the comment.

It is genuinely pre-existing: the same shape applied to #13857's eligibility refusals and the reviewer classed it out of that PR's scope. What is new is that #14033 made the claim explicit in prose, so the contradiction is now readable.

What is NOT in question

Nothing in #14033's ruled behaviour: the gate, its placement before the record probe and the usage stamp, the three governed mint paths and the null-shape equality are all pinned, and the delta review PASSed with zero blocking findings. This card does not reopen any of that.

The shapes

  • A · gate the probe on the standing policy — read publicSharing.enabled before the probe; when it is off, fall through to the generic 404 for every arm. Links on a switched-off object become uniformly indistinguishable from unknown tokens.
  • B · leave it, and say so — keep the 401 affordance, and add a comment at both probe sites recording that the route layer deliberately accepts the oracle, so the service's comment stops being contradicted.
  • C · gate only the two 401 arms, leave the 410 EXPIRED_OR_REVOKED arm answering from the row.

Common to A and C: the fix must land at both sites — the plugin route and the runtime dispatcher twin — or the oracle simply moves to whichever embedding uses the other one.

<!-- os-decision-facets -->

四棱分析(分诊席出具,供裁决)

① 长期健全性(权重 ≥50%,主导本建议)—— 指向 A。
真正的缺陷不是「多答了一个 401」,而是同一个安全属性被写在一层、又被上一层拆掉。服务层把威胁模型逐字写下来了(「a distinguishable 'sharing is off for this object' is an existence oracle」),路由层照旧泄露。这种双层不一致不会稳定存在:下一个读到服务层注释的人会相信它,并在一个假前提上继续写代码 —— 这比从来没声明过更坏。A 把属性收回一处;B 至少让两层说同一句话;C 留下「哪几个 arm 被门住」的规则,属性仍不在一处。

② 真实业务拉力 —— 微弱,且方向偏 A。
B 保住的那个体验是:告诉用户「这条链接需要密码」—— 而该链接所在对象的分享开关是关的,即便密码正确也什么都取不到。那是在教用户开一扇已经砌死的门。没有测到任何消费者依赖这条消息;真正会遇到它的是拿着旧链接的正当用户,而他们无论如何都取不到内容,404 与 401 对他们的最终结果相同。

③ 防 AI 编码错误 —— 强烈指向 A。
当前形状是个陷阱:agent 读 share-link-service.ts 那段注释会正确地推出「存在性预言已关闭」,据此写一个断言 404 的测试 —— 在服务层过、在 HTTP 层假。两层互相矛盾正是产出「自信而错误」代码的典型形状。⚠️ 附带的第二个陷阱:探针在 share-link-routes.tsruntime/src/domains/share-links.ts 各有一份重复实现,只改一处是可预期的失败模式,派工时必须点名两处。

④ 创业阶段不增殖 —— 指向 A,明确反对 C。
A 不新增概念、不新增标签、不新增配置开关,只是把一次已有的读提前。C 会造出「第三类链接应答」和一条「哪些 arm 受门禁」的规则,是本轴要避免的增殖。

建议:A —— 探针整体门在 publicSharing.enabled 之后,两处同笔改。

回退:B,但不得沉默。 若维护者判断 401 提示对支持工作是承重的,那就选 B 并在两个探针处写下「路由层明知且有意接受该预言」,同时修正服务层注释使其不再宣称已关闭。⛔ 三个选项里唯一不可接受的是什么都不做:留着两层互相矛盾的注释,是本卡真正要消灭的东西。

⚠️ 置信缺口(必录): 我没有测 objectui。若 share-link 查看器依赖 401 NEEDS_PASSWORD 这个状态码来渲染密码输入框,那么 A 会改变一条已发布的前端路径 —— 对关掉开关的对象的链接而言,用户看到的将从密码框变成「链接无效」。这条我读不到(跨仓,且本席不改代码),裁决前应由 repo:objectui 侧确认。这是本分析里唯一没有实测支撑的环节。

Re-check:git show origin/main:packages/plugins/plugin-sharing/src/share-link-routes.ts | sed -n '238,262p',以及 git show origin/main:packages/runtime/src/domains/share-links.ts | sed -n '145,163p'

Refs: #14033 · PR #14580 · #13857(同族的 eligibility 半边)· #14581 · #14582 · #14668(拆出的 changeset 措辞半边)

Generated by Claude Code

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

      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
       blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
      }
      } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
      })();
      (function(){
      try {
      var __m = "github.com";
      var __re = new RegExp('^' + "github\\.com" + '
      
      Skip to content

      [Decision] The share-link route probe re-opens the existence oracle that share-link-service deliberately closed — a switched-off link with a password still answers 401 #14637

      Description

      @os-sales

      Filed by the domain:services PM seat (session session_01AUF1NoViznQK32gqpK8wS8) from the non-blocking notes of the in-seat Clause-② contract review of PR #14580 (#14033) — round 1 note 5, adopted verbatim on 14033#issuecomment-5511376156. Re-measured by the triage seat at origin/main2aa8456.

      Item 2 of the original filing (the changeset's "burst the log once" wording) is split to #14668 and is dispatchable now — it is not held behind this ruling.

      The defect

      resolveToken refuses a link whose object has publicSharing.enabled off, and the refusal is the undifferentiated null the #14033 ruling asked for — over HTTP a 404 INVALID_OR_EXPIRED, byte-identical to an unknown token, pinned at share-link-eligibility.test.ts:992-1022.

      But the route's probe runs afterresolveToken returns null and answers from the row, with no knowledge of the object's block:

      • packages/plugins/plugin-sharing/src/share-link-routes.ts401 NEEDS_PASSWORD / WRONG_PASSWORD for a row carrying password_hash; 401 SIGN_IN_REQUIRED for audience === 'signed_in' without a signed-in viewer
      • packages/runtime/src/domains/share-links.tsa duplicated twin of the same probe, same arms, same codes

      So for those two link shapes an anonymous caller can still tell a real-but-switched-off token from an unknown one, and a correct password on such a link answers WRONG_PASSWORD.

      ⭐ Why this is more than "pre-existing, out of scope"

      The service layer wrote the threat model down, in the same feature, immediately above the arm that closes it:

      …for a caller who may hold nothing but a token, a distinguishable "sharing is off for this object" is an existence oracle, so the answer is the one revoked / expired / unknown / ineligible already give (over HTTP the generic 404).

      The route above it then re-opens exactly that oracle for two of the three shapes. This is not a gap someone forgot to close — it is a security property that is stated in one layer and defeated in the layer above it, which is strictly worse than never having claimed it, because the next reader believes the comment.

      It is genuinely pre-existing: the same shape applied to #13857's eligibility refusals and the reviewer classed it out of that PR's scope. What is new is that #14033 made the claim explicit in prose, so the contradiction is now readable.

      What is NOT in question

      Nothing in #14033's ruled behaviour: the gate, its placement before the record probe and the usage stamp, the three governed mint paths and the null-shape equality are all pinned, and the delta review PASSed with zero blocking findings. This card does not reopen any of that.

      The shapes

      • A · gate the probe on the standing policy — read publicSharing.enabled before the probe; when it is off, fall through to the generic 404 for every arm. Links on a switched-off object become uniformly indistinguishable from unknown tokens.
      • B · leave it, and say so — keep the 401 affordance, and add a comment at both probe sites recording that the route layer deliberately accepts the oracle, so the service's comment stops being contradicted.
      • C · gate only the two 401 arms, leave the 410 EXPIRED_OR_REVOKED arm answering from the row.

      Common to A and C: the fix must land at both sites — the plugin route and the runtime dispatcher twin — or the oracle simply moves to whichever embedding uses the other one.

      <!-- os-decision-facets -->

      四棱分析(分诊席出具,供裁决)

      ① 长期健全性(权重 ≥50%,主导本建议)—— 指向 A。
      真正的缺陷不是「多答了一个 401」,而是同一个安全属性被写在一层、又被上一层拆掉。服务层把威胁模型逐字写下来了(「a distinguishable 'sharing is off for this object' is an existence oracle」),路由层照旧泄露。这种双层不一致不会稳定存在:下一个读到服务层注释的人会相信它,并在一个假前提上继续写代码 —— 这比从来没声明过更坏。A 把属性收回一处;B 至少让两层说同一句话;C 留下「哪几个 arm 被门住」的规则,属性仍不在一处。

      ② 真实业务拉力 —— 微弱,且方向偏 A。
      B 保住的那个体验是:告诉用户「这条链接需要密码」—— 而该链接所在对象的分享开关是关的,即便密码正确也什么都取不到。那是在教用户开一扇已经砌死的门。没有测到任何消费者依赖这条消息;真正会遇到它的是拿着旧链接的正当用户,而他们无论如何都取不到内容,404 与 401 对他们的最终结果相同。

      ③ 防 AI 编码错误 —— 强烈指向 A。
      当前形状是个陷阱:agent 读 share-link-service.ts 那段注释会正确地推出「存在性预言已关闭」,据此写一个断言 404 的测试 —— 在服务层过、在 HTTP 层假。两层互相矛盾正是产出「自信而错误」代码的典型形状。⚠️ 附带的第二个陷阱:探针在 share-link-routes.tsruntime/src/domains/share-links.ts 各有一份重复实现,只改一处是可预期的失败模式,派工时必须点名两处。

      ④ 创业阶段不增殖 —— 指向 A,明确反对 C。
      A 不新增概念、不新增标签、不新增配置开关,只是把一次已有的读提前。C 会造出「第三类链接应答」和一条「哪些 arm 受门禁」的规则,是本轴要避免的增殖。

      建议:A —— 探针整体门在 publicSharing.enabled 之后,两处同笔改。

      回退:B,但不得沉默。 若维护者判断 401 提示对支持工作是承重的,那就选 B 并在两个探针处写下「路由层明知且有意接受该预言」,同时修正服务层注释使其不再宣称已关闭。⛔ 三个选项里唯一不可接受的是什么都不做:留着两层互相矛盾的注释,是本卡真正要消灭的东西。

      ⚠️ 置信缺口(必录): 我没有测 objectui。若 share-link 查看器依赖 401 NEEDS_PASSWORD 这个状态码来渲染密码输入框,那么 A 会改变一条已发布的前端路径 —— 对关掉开关的对象的链接而言,用户看到的将从密码框变成「链接无效」。这条我读不到(跨仓,且本席不改代码),裁决前应由 repo:objectui 侧确认。这是本分析里唯一没有实测支撑的环节。

      Re-check:git show origin/main:packages/plugins/plugin-sharing/src/share-link-routes.ts | sed -n '238,262p',以及 git show origin/main:packages/runtime/src/domains/share-links.ts | sed -n '145,163p'

      Refs: #14033 · PR #14580 · #13857(同族的 eligibility 半边)· #14581 · #14582 · #14668(拆出的 changeset 措辞半边)

      Generated by Claude Code

      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

          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
          Skip to content

          [Decision] The share-link route probe re-opens the existence oracle that share-link-service deliberately closed — a switched-off link with a password still answers 401 #14637

          Description

          @os-sales

          Filed by the domain:services PM seat (session session_01AUF1NoViznQK32gqpK8wS8) from the non-blocking notes of the in-seat Clause-② contract review of PR #14580 (#14033) — round 1 note 5, adopted verbatim on 14033#issuecomment-5511376156. Re-measured by the triage seat at origin/main2aa8456.

          Item 2 of the original filing (the changeset's "burst the log once" wording) is split to #14668 and is dispatchable now — it is not held behind this ruling.

          The defect

          resolveToken refuses a link whose object has publicSharing.enabled off, and the refusal is the undifferentiated null the #14033 ruling asked for — over HTTP a 404 INVALID_OR_EXPIRED, byte-identical to an unknown token, pinned at share-link-eligibility.test.ts:992-1022.

          But the route's probe runs afterresolveToken returns null and answers from the row, with no knowledge of the object's block:

          • packages/plugins/plugin-sharing/src/share-link-routes.ts401 NEEDS_PASSWORD / WRONG_PASSWORD for a row carrying password_hash; 401 SIGN_IN_REQUIRED for audience === 'signed_in' without a signed-in viewer
          • packages/runtime/src/domains/share-links.tsa duplicated twin of the same probe, same arms, same codes

          So for those two link shapes an anonymous caller can still tell a real-but-switched-off token from an unknown one, and a correct password on such a link answers WRONG_PASSWORD.

          ⭐ Why this is more than "pre-existing, out of scope"

          The service layer wrote the threat model down, in the same feature, immediately above the arm that closes it:

          …for a caller who may hold nothing but a token, a distinguishable "sharing is off for this object" is an existence oracle, so the answer is the one revoked / expired / unknown / ineligible already give (over HTTP the generic 404).

          The route above it then re-opens exactly that oracle for two of the three shapes. This is not a gap someone forgot to close — it is a security property that is stated in one layer and defeated in the layer above it, which is strictly worse than never having claimed it, because the next reader believes the comment.

          It is genuinely pre-existing: the same shape applied to #13857's eligibility refusals and the reviewer classed it out of that PR's scope. What is new is that #14033 made the claim explicit in prose, so the contradiction is now readable.

          What is NOT in question

          Nothing in #14033's ruled behaviour: the gate, its placement before the record probe and the usage stamp, the three governed mint paths and the null-shape equality are all pinned, and the delta review PASSed with zero blocking findings. This card does not reopen any of that.

          The shapes

          • A · gate the probe on the standing policy — read publicSharing.enabled before the probe; when it is off, fall through to the generic 404 for every arm. Links on a switched-off object become uniformly indistinguishable from unknown tokens.
          • B · leave it, and say so — keep the 401 affordance, and add a comment at both probe sites recording that the route layer deliberately accepts the oracle, so the service's comment stops being contradicted.
          • C · gate only the two 401 arms, leave the 410 EXPIRED_OR_REVOKED arm answering from the row.

          Common to A and C: the fix must land at both sites — the plugin route and the runtime dispatcher twin — or the oracle simply moves to whichever embedding uses the other one.

          <!-- os-decision-facets -->

          四棱分析(分诊席出具,供裁决)

          ① 长期健全性(权重 ≥50%,主导本建议)—— 指向 A。
          真正的缺陷不是「多答了一个 401」,而是同一个安全属性被写在一层、又被上一层拆掉。服务层把威胁模型逐字写下来了(「a distinguishable 'sharing is off for this object' is an existence oracle」),路由层照旧泄露。这种双层不一致不会稳定存在:下一个读到服务层注释的人会相信它,并在一个假前提上继续写代码 —— 这比从来没声明过更坏。A 把属性收回一处;B 至少让两层说同一句话;C 留下「哪几个 arm 被门住」的规则,属性仍不在一处。

          ② 真实业务拉力 —— 微弱,且方向偏 A。
          B 保住的那个体验是:告诉用户「这条链接需要密码」—— 而该链接所在对象的分享开关是关的,即便密码正确也什么都取不到。那是在教用户开一扇已经砌死的门。没有测到任何消费者依赖这条消息;真正会遇到它的是拿着旧链接的正当用户,而他们无论如何都取不到内容,404 与 401 对他们的最终结果相同。

          ③ 防 AI 编码错误 —— 强烈指向 A。
          当前形状是个陷阱:agent 读 share-link-service.ts 那段注释会正确地推出「存在性预言已关闭」,据此写一个断言 404 的测试 —— 在服务层过、在 HTTP 层假。两层互相矛盾正是产出「自信而错误」代码的典型形状。⚠️ 附带的第二个陷阱:探针在 share-link-routes.tsruntime/src/domains/share-links.ts 各有一份重复实现,只改一处是可预期的失败模式,派工时必须点名两处。

          ④ 创业阶段不增殖 —— 指向 A,明确反对 C。
          A 不新增概念、不新增标签、不新增配置开关,只是把一次已有的读提前。C 会造出「第三类链接应答」和一条「哪些 arm 受门禁」的规则,是本轴要避免的增殖。

          建议:A —— 探针整体门在 publicSharing.enabled 之后,两处同笔改。

          回退:B,但不得沉默。 若维护者判断 401 提示对支持工作是承重的,那就选 B 并在两个探针处写下「路由层明知且有意接受该预言」,同时修正服务层注释使其不再宣称已关闭。⛔ 三个选项里唯一不可接受的是什么都不做:留着两层互相矛盾的注释,是本卡真正要消灭的东西。

          ⚠️ 置信缺口(必录): 我没有测 objectui。若 share-link 查看器依赖 401 NEEDS_PASSWORD 这个状态码来渲染密码输入框,那么 A 会改变一条已发布的前端路径 —— 对关掉开关的对象的链接而言,用户看到的将从密码框变成「链接无效」。这条我读不到(跨仓,且本席不改代码),裁决前应由 repo:objectui 侧确认。这是本分析里唯一没有实测支撑的环节。

          Re-check:git show origin/main:packages/plugins/plugin-sharing/src/share-link-routes.ts | sed -n '238,262p',以及 git show origin/main:packages/runtime/src/domains/share-links.ts | sed -n '145,163p'

          Refs: #14033 · PR #14580 · #13857(同族的 eligibility 半边)· #14581 · #14582 · #14668(拆出的 changeset 措辞半边)

          Generated by Claude Code

          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

              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
              Skip to content

              [Decision] The share-link route probe re-opens the existence oracle that share-link-service deliberately closed — a switched-off link with a password still answers 401 #14637

              Description

              @os-sales

              Filed by the domain:services PM seat (session session_01AUF1NoViznQK32gqpK8wS8) from the non-blocking notes of the in-seat Clause-② contract review of PR #14580 (#14033) — round 1 note 5, adopted verbatim on 14033#issuecomment-5511376156. Re-measured by the triage seat at origin/main2aa8456.

              Item 2 of the original filing (the changeset's "burst the log once" wording) is split to #14668 and is dispatchable now — it is not held behind this ruling.

              The defect

              resolveToken refuses a link whose object has publicSharing.enabled off, and the refusal is the undifferentiated null the #14033 ruling asked for — over HTTP a 404 INVALID_OR_EXPIRED, byte-identical to an unknown token, pinned at share-link-eligibility.test.ts:992-1022.

              But the route's probe runs afterresolveToken returns null and answers from the row, with no knowledge of the object's block:

              • packages/plugins/plugin-sharing/src/share-link-routes.ts401 NEEDS_PASSWORD / WRONG_PASSWORD for a row carrying password_hash; 401 SIGN_IN_REQUIRED for audience === 'signed_in' without a signed-in viewer
              • packages/runtime/src/domains/share-links.tsa duplicated twin of the same probe, same arms, same codes

              So for those two link shapes an anonymous caller can still tell a real-but-switched-off token from an unknown one, and a correct password on such a link answers WRONG_PASSWORD.

              ⭐ Why this is more than "pre-existing, out of scope"

              The service layer wrote the threat model down, in the same feature, immediately above the arm that closes it:

              …for a caller who may hold nothing but a token, a distinguishable "sharing is off for this object" is an existence oracle, so the answer is the one revoked / expired / unknown / ineligible already give (over HTTP the generic 404).

              The route above it then re-opens exactly that oracle for two of the three shapes. This is not a gap someone forgot to close — it is a security property that is stated in one layer and defeated in the layer above it, which is strictly worse than never having claimed it, because the next reader believes the comment.

              It is genuinely pre-existing: the same shape applied to #13857's eligibility refusals and the reviewer classed it out of that PR's scope. What is new is that #14033 made the claim explicit in prose, so the contradiction is now readable.

              What is NOT in question

              Nothing in #14033's ruled behaviour: the gate, its placement before the record probe and the usage stamp, the three governed mint paths and the null-shape equality are all pinned, and the delta review PASSed with zero blocking findings. This card does not reopen any of that.

              The shapes

              • A · gate the probe on the standing policy — read publicSharing.enabled before the probe; when it is off, fall through to the generic 404 for every arm. Links on a switched-off object become uniformly indistinguishable from unknown tokens.
              • B · leave it, and say so — keep the 401 affordance, and add a comment at both probe sites recording that the route layer deliberately accepts the oracle, so the service's comment stops being contradicted.
              • C · gate only the two 401 arms, leave the 410 EXPIRED_OR_REVOKED arm answering from the row.

              Common to A and C: the fix must land at both sites — the plugin route and the runtime dispatcher twin — or the oracle simply moves to whichever embedding uses the other one.

              <!-- os-decision-facets -->

              四棱分析(分诊席出具,供裁决)

              ① 长期健全性(权重 ≥50%,主导本建议)—— 指向 A。
              真正的缺陷不是「多答了一个 401」,而是同一个安全属性被写在一层、又被上一层拆掉。服务层把威胁模型逐字写下来了(「a distinguishable 'sharing is off for this object' is an existence oracle」),路由层照旧泄露。这种双层不一致不会稳定存在:下一个读到服务层注释的人会相信它,并在一个假前提上继续写代码 —— 这比从来没声明过更坏。A 把属性收回一处;B 至少让两层说同一句话;C 留下「哪几个 arm 被门住」的规则,属性仍不在一处。

              ② 真实业务拉力 —— 微弱,且方向偏 A。
              B 保住的那个体验是:告诉用户「这条链接需要密码」—— 而该链接所在对象的分享开关是关的,即便密码正确也什么都取不到。那是在教用户开一扇已经砌死的门。没有测到任何消费者依赖这条消息;真正会遇到它的是拿着旧链接的正当用户,而他们无论如何都取不到内容,404 与 401 对他们的最终结果相同。

              ③ 防 AI 编码错误 —— 强烈指向 A。
              当前形状是个陷阱:agent 读 share-link-service.ts 那段注释会正确地推出「存在性预言已关闭」,据此写一个断言 404 的测试 —— 在服务层过、在 HTTP 层假。两层互相矛盾正是产出「自信而错误」代码的典型形状。⚠️ 附带的第二个陷阱:探针在 share-link-routes.tsruntime/src/domains/share-links.ts 各有一份重复实现,只改一处是可预期的失败模式,派工时必须点名两处。

              ④ 创业阶段不增殖 —— 指向 A,明确反对 C。
              A 不新增概念、不新增标签、不新增配置开关,只是把一次已有的读提前。C 会造出「第三类链接应答」和一条「哪些 arm 受门禁」的规则,是本轴要避免的增殖。

              建议:A —— 探针整体门在 publicSharing.enabled 之后,两处同笔改。

              回退:B,但不得沉默。 若维护者判断 401 提示对支持工作是承重的,那就选 B 并在两个探针处写下「路由层明知且有意接受该预言」,同时修正服务层注释使其不再宣称已关闭。⛔ 三个选项里唯一不可接受的是什么都不做:留着两层互相矛盾的注释,是本卡真正要消灭的东西。

              ⚠️ 置信缺口(必录): 我没有测 objectui。若 share-link 查看器依赖 401 NEEDS_PASSWORD 这个状态码来渲染密码输入框,那么 A 会改变一条已发布的前端路径 —— 对关掉开关的对象的链接而言,用户看到的将从密码框变成「链接无效」。这条我读不到(跨仓,且本席不改代码),裁决前应由 repo:objectui 侧确认。这是本分析里唯一没有实测支撑的环节。

              Re-check:git show origin/main:packages/plugins/plugin-sharing/src/share-link-routes.ts | sed -n '238,262p',以及 git show origin/main:packages/runtime/src/domains/share-links.ts | sed -n '145,163p'

              Refs: #14033 · PR #14580 · #13857(同族的 eligibility 半边)· #14581 · #14582 · #14668(拆出的 changeset 措辞半边)

              Generated by Claude Code

              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

                  , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
                  Skip to content

                  [Decision] The share-link route probe re-opens the existence oracle that share-link-service deliberately closed — a switched-off link with a password still answers 401 #14637

                  Description

                  @os-sales

                  Filed by the domain:services PM seat (session session_01AUF1NoViznQK32gqpK8wS8) from the non-blocking notes of the in-seat Clause-② contract review of PR #14580 (#14033) — round 1 note 5, adopted verbatim on 14033#issuecomment-5511376156. Re-measured by the triage seat at origin/main2aa8456.

                  Item 2 of the original filing (the changeset's "burst the log once" wording) is split to #14668 and is dispatchable now — it is not held behind this ruling.

                  The defect

                  resolveToken refuses a link whose object has publicSharing.enabled off, and the refusal is the undifferentiated null the #14033 ruling asked for — over HTTP a 404 INVALID_OR_EXPIRED, byte-identical to an unknown token, pinned at share-link-eligibility.test.ts:992-1022.

                  But the route's probe runs afterresolveToken returns null and answers from the row, with no knowledge of the object's block:

                  • packages/plugins/plugin-sharing/src/share-link-routes.ts401 NEEDS_PASSWORD / WRONG_PASSWORD for a row carrying password_hash; 401 SIGN_IN_REQUIRED for audience === 'signed_in' without a signed-in viewer
                  • packages/runtime/src/domains/share-links.tsa duplicated twin of the same probe, same arms, same codes

                  So for those two link shapes an anonymous caller can still tell a real-but-switched-off token from an unknown one, and a correct password on such a link answers WRONG_PASSWORD.

                  ⭐ Why this is more than "pre-existing, out of scope"

                  The service layer wrote the threat model down, in the same feature, immediately above the arm that closes it:

                  …for a caller who may hold nothing but a token, a distinguishable "sharing is off for this object" is an existence oracle, so the answer is the one revoked / expired / unknown / ineligible already give (over HTTP the generic 404).

                  The route above it then re-opens exactly that oracle for two of the three shapes. This is not a gap someone forgot to close — it is a security property that is stated in one layer and defeated in the layer above it, which is strictly worse than never having claimed it, because the next reader believes the comment.

                  It is genuinely pre-existing: the same shape applied to #13857's eligibility refusals and the reviewer classed it out of that PR's scope. What is new is that #14033 made the claim explicit in prose, so the contradiction is now readable.

                  What is NOT in question

                  Nothing in #14033's ruled behaviour: the gate, its placement before the record probe and the usage stamp, the three governed mint paths and the null-shape equality are all pinned, and the delta review PASSed with zero blocking findings. This card does not reopen any of that.

                  The shapes

                  • A · gate the probe on the standing policy — read publicSharing.enabled before the probe; when it is off, fall through to the generic 404 for every arm. Links on a switched-off object become uniformly indistinguishable from unknown tokens.
                  • B · leave it, and say so — keep the 401 affordance, and add a comment at both probe sites recording that the route layer deliberately accepts the oracle, so the service's comment stops being contradicted.
                  • C · gate only the two 401 arms, leave the 410 EXPIRED_OR_REVOKED arm answering from the row.

                  Common to A and C: the fix must land at both sites — the plugin route and the runtime dispatcher twin — or the oracle simply moves to whichever embedding uses the other one.

                  <!-- os-decision-facets -->

                  四棱分析(分诊席出具,供裁决)

                  ① 长期健全性(权重 ≥50%,主导本建议)—— 指向 A。
                  真正的缺陷不是「多答了一个 401」,而是同一个安全属性被写在一层、又被上一层拆掉。服务层把威胁模型逐字写下来了(「a distinguishable 'sharing is off for this object' is an existence oracle」),路由层照旧泄露。这种双层不一致不会稳定存在:下一个读到服务层注释的人会相信它,并在一个假前提上继续写代码 —— 这比从来没声明过更坏。A 把属性收回一处;B 至少让两层说同一句话;C 留下「哪几个 arm 被门住」的规则,属性仍不在一处。

                  ② 真实业务拉力 —— 微弱,且方向偏 A。
                  B 保住的那个体验是:告诉用户「这条链接需要密码」—— 而该链接所在对象的分享开关是关的,即便密码正确也什么都取不到。那是在教用户开一扇已经砌死的门。没有测到任何消费者依赖这条消息;真正会遇到它的是拿着旧链接的正当用户,而他们无论如何都取不到内容,404 与 401 对他们的最终结果相同。

                  ③ 防 AI 编码错误 —— 强烈指向 A。
                  当前形状是个陷阱:agent 读 share-link-service.ts 那段注释会正确地推出「存在性预言已关闭」,据此写一个断言 404 的测试 —— 在服务层过、在 HTTP 层假。两层互相矛盾正是产出「自信而错误」代码的典型形状。⚠️ 附带的第二个陷阱:探针在 share-link-routes.tsruntime/src/domains/share-links.ts 各有一份重复实现,只改一处是可预期的失败模式,派工时必须点名两处。

                  ④ 创业阶段不增殖 —— 指向 A,明确反对 C。
                  A 不新增概念、不新增标签、不新增配置开关,只是把一次已有的读提前。C 会造出「第三类链接应答」和一条「哪些 arm 受门禁」的规则,是本轴要避免的增殖。

                  建议:A —— 探针整体门在 publicSharing.enabled 之后,两处同笔改。

                  回退:B,但不得沉默。 若维护者判断 401 提示对支持工作是承重的,那就选 B 并在两个探针处写下「路由层明知且有意接受该预言」,同时修正服务层注释使其不再宣称已关闭。⛔ 三个选项里唯一不可接受的是什么都不做:留着两层互相矛盾的注释,是本卡真正要消灭的东西。

                  ⚠️ 置信缺口(必录): 我没有测 objectui。若 share-link 查看器依赖 401 NEEDS_PASSWORD 这个状态码来渲染密码输入框,那么 A 会改变一条已发布的前端路径 —— 对关掉开关的对象的链接而言,用户看到的将从密码框变成「链接无效」。这条我读不到(跨仓,且本席不改代码),裁决前应由 repo:objectui 侧确认。这是本分析里唯一没有实测支撑的环节。

                  Re-check:git show origin/main:packages/plugins/plugin-sharing/src/share-link-routes.ts | sed -n '238,262p',以及 git show origin/main:packages/runtime/src/domains/share-links.ts | sed -n '145,163p'

                  Refs: #14033 · PR #14580 · #13857(同族的 eligibility 半边)· #14581 · #14582 · #14668(拆出的 changeset 措辞半边)

                  Generated by Claude Code

                  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

                      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
                      Skip to content

                      [Decision] The share-link route probe re-opens the existence oracle that share-link-service deliberately closed — a switched-off link with a password still answers 401 #14637

                      Description

                      @os-sales

                      Filed by the domain:services PM seat (session session_01AUF1NoViznQK32gqpK8wS8) from the non-blocking notes of the in-seat Clause-② contract review of PR #14580 (#14033) — round 1 note 5, adopted verbatim on 14033#issuecomment-5511376156. Re-measured by the triage seat at origin/main2aa8456.

                      Item 2 of the original filing (the changeset's "burst the log once" wording) is split to #14668 and is dispatchable now — it is not held behind this ruling.

                      The defect

                      resolveToken refuses a link whose object has publicSharing.enabled off, and the refusal is the undifferentiated null the #14033 ruling asked for — over HTTP a 404 INVALID_OR_EXPIRED, byte-identical to an unknown token, pinned at share-link-eligibility.test.ts:992-1022.

                      But the route's probe runs afterresolveToken returns null and answers from the row, with no knowledge of the object's block:

                      • packages/plugins/plugin-sharing/src/share-link-routes.ts401 NEEDS_PASSWORD / WRONG_PASSWORD for a row carrying password_hash; 401 SIGN_IN_REQUIRED for audience === 'signed_in' without a signed-in viewer
                      • packages/runtime/src/domains/share-links.tsa duplicated twin of the same probe, same arms, same codes

                      So for those two link shapes an anonymous caller can still tell a real-but-switched-off token from an unknown one, and a correct password on such a link answers WRONG_PASSWORD.

                      ⭐ Why this is more than "pre-existing, out of scope"

                      The service layer wrote the threat model down, in the same feature, immediately above the arm that closes it:

                      …for a caller who may hold nothing but a token, a distinguishable "sharing is off for this object" is an existence oracle, so the answer is the one revoked / expired / unknown / ineligible already give (over HTTP the generic 404).

                      The route above it then re-opens exactly that oracle for two of the three shapes. This is not a gap someone forgot to close — it is a security property that is stated in one layer and defeated in the layer above it, which is strictly worse than never having claimed it, because the next reader believes the comment.

                      It is genuinely pre-existing: the same shape applied to #13857's eligibility refusals and the reviewer classed it out of that PR's scope. What is new is that #14033 made the claim explicit in prose, so the contradiction is now readable.

                      What is NOT in question

                      Nothing in #14033's ruled behaviour: the gate, its placement before the record probe and the usage stamp, the three governed mint paths and the null-shape equality are all pinned, and the delta review PASSed with zero blocking findings. This card does not reopen any of that.

                      The shapes

                      • A · gate the probe on the standing policy — read publicSharing.enabled before the probe; when it is off, fall through to the generic 404 for every arm. Links on a switched-off object become uniformly indistinguishable from unknown tokens.
                      • B · leave it, and say so — keep the 401 affordance, and add a comment at both probe sites recording that the route layer deliberately accepts the oracle, so the service's comment stops being contradicted.
                      • C · gate only the two 401 arms, leave the 410 EXPIRED_OR_REVOKED arm answering from the row.

                      Common to A and C: the fix must land at both sites — the plugin route and the runtime dispatcher twin — or the oracle simply moves to whichever embedding uses the other one.

                      <!-- os-decision-facets -->

                      四棱分析(分诊席出具,供裁决)

                      ① 长期健全性(权重 ≥50%,主导本建议)—— 指向 A。
                      真正的缺陷不是「多答了一个 401」,而是同一个安全属性被写在一层、又被上一层拆掉。服务层把威胁模型逐字写下来了(「a distinguishable 'sharing is off for this object' is an existence oracle」),路由层照旧泄露。这种双层不一致不会稳定存在:下一个读到服务层注释的人会相信它,并在一个假前提上继续写代码 —— 这比从来没声明过更坏。A 把属性收回一处;B 至少让两层说同一句话;C 留下「哪几个 arm 被门住」的规则,属性仍不在一处。

                      ② 真实业务拉力 —— 微弱,且方向偏 A。
                      B 保住的那个体验是:告诉用户「这条链接需要密码」—— 而该链接所在对象的分享开关是关的,即便密码正确也什么都取不到。那是在教用户开一扇已经砌死的门。没有测到任何消费者依赖这条消息;真正会遇到它的是拿着旧链接的正当用户,而他们无论如何都取不到内容,404 与 401 对他们的最终结果相同。

                      ③ 防 AI 编码错误 —— 强烈指向 A。
                      当前形状是个陷阱:agent 读 share-link-service.ts 那段注释会正确地推出「存在性预言已关闭」,据此写一个断言 404 的测试 —— 在服务层过、在 HTTP 层假。两层互相矛盾正是产出「自信而错误」代码的典型形状。⚠️ 附带的第二个陷阱:探针在 share-link-routes.tsruntime/src/domains/share-links.ts 各有一份重复实现,只改一处是可预期的失败模式,派工时必须点名两处。

                      ④ 创业阶段不增殖 —— 指向 A,明确反对 C。
                      A 不新增概念、不新增标签、不新增配置开关,只是把一次已有的读提前。C 会造出「第三类链接应答」和一条「哪些 arm 受门禁」的规则,是本轴要避免的增殖。

                      建议:A —— 探针整体门在 publicSharing.enabled 之后,两处同笔改。

                      回退:B,但不得沉默。 若维护者判断 401 提示对支持工作是承重的,那就选 B 并在两个探针处写下「路由层明知且有意接受该预言」,同时修正服务层注释使其不再宣称已关闭。⛔ 三个选项里唯一不可接受的是什么都不做:留着两层互相矛盾的注释,是本卡真正要消灭的东西。

                      ⚠️ 置信缺口(必录): 我没有测 objectui。若 share-link 查看器依赖 401 NEEDS_PASSWORD 这个状态码来渲染密码输入框,那么 A 会改变一条已发布的前端路径 —— 对关掉开关的对象的链接而言,用户看到的将从密码框变成「链接无效」。这条我读不到(跨仓,且本席不改代码),裁决前应由 repo:objectui 侧确认。这是本分析里唯一没有实测支撑的环节。

                      Re-check:git show origin/main:packages/plugins/plugin-sharing/src/share-link-routes.ts | sed -n '238,262p',以及 git show origin/main:packages/runtime/src/domains/share-links.ts | sed -n '145,163p'

                      Refs: #14033 · PR #14580 · #13857(同族的 eligibility 半边)· #14581 · #14582 · #14668(拆出的 changeset 措辞半边)

                      Generated by Claude Code

                      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

                          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
                          Skip to content

                          [Decision] The share-link route probe re-opens the existence oracle that share-link-service deliberately closed — a switched-off link with a password still answers 401 #14637

                          Description

                          @os-sales

                          Filed by the domain:services PM seat (session session_01AUF1NoViznQK32gqpK8wS8) from the non-blocking notes of the in-seat Clause-② contract review of PR #14580 (#14033) — round 1 note 5, adopted verbatim on 14033#issuecomment-5511376156. Re-measured by the triage seat at origin/main2aa8456.

                          Item 2 of the original filing (the changeset's "burst the log once" wording) is split to #14668 and is dispatchable now — it is not held behind this ruling.

                          The defect

                          resolveToken refuses a link whose object has publicSharing.enabled off, and the refusal is the undifferentiated null the #14033 ruling asked for — over HTTP a 404 INVALID_OR_EXPIRED, byte-identical to an unknown token, pinned at share-link-eligibility.test.ts:992-1022.

                          But the route's probe runs afterresolveToken returns null and answers from the row, with no knowledge of the object's block:

                          • packages/plugins/plugin-sharing/src/share-link-routes.ts401 NEEDS_PASSWORD / WRONG_PASSWORD for a row carrying password_hash; 401 SIGN_IN_REQUIRED for audience === 'signed_in' without a signed-in viewer
                          • packages/runtime/src/domains/share-links.tsa duplicated twin of the same probe, same arms, same codes

                          So for those two link shapes an anonymous caller can still tell a real-but-switched-off token from an unknown one, and a correct password on such a link answers WRONG_PASSWORD.

                          ⭐ Why this is more than "pre-existing, out of scope"

                          The service layer wrote the threat model down, in the same feature, immediately above the arm that closes it:

                          …for a caller who may hold nothing but a token, a distinguishable "sharing is off for this object" is an existence oracle, so the answer is the one revoked / expired / unknown / ineligible already give (over HTTP the generic 404).

                          The route above it then re-opens exactly that oracle for two of the three shapes. This is not a gap someone forgot to close — it is a security property that is stated in one layer and defeated in the layer above it, which is strictly worse than never having claimed it, because the next reader believes the comment.

                          It is genuinely pre-existing: the same shape applied to #13857's eligibility refusals and the reviewer classed it out of that PR's scope. What is new is that #14033 made the claim explicit in prose, so the contradiction is now readable.

                          What is NOT in question

                          Nothing in #14033's ruled behaviour: the gate, its placement before the record probe and the usage stamp, the three governed mint paths and the null-shape equality are all pinned, and the delta review PASSed with zero blocking findings. This card does not reopen any of that.

                          The shapes

                          • A · gate the probe on the standing policy — read publicSharing.enabled before the probe; when it is off, fall through to the generic 404 for every arm. Links on a switched-off object become uniformly indistinguishable from unknown tokens.
                          • B · leave it, and say so — keep the 401 affordance, and add a comment at both probe sites recording that the route layer deliberately accepts the oracle, so the service's comment stops being contradicted.
                          • C · gate only the two 401 arms, leave the 410 EXPIRED_OR_REVOKED arm answering from the row.

                          Common to A and C: the fix must land at both sites — the plugin route and the runtime dispatcher twin — or the oracle simply moves to whichever embedding uses the other one.

                          <!-- os-decision-facets -->

                          四棱分析(分诊席出具,供裁决)

                          ① 长期健全性(权重 ≥50%,主导本建议)—— 指向 A。
                          真正的缺陷不是「多答了一个 401」,而是同一个安全属性被写在一层、又被上一层拆掉。服务层把威胁模型逐字写下来了(「a distinguishable 'sharing is off for this object' is an existence oracle」),路由层照旧泄露。这种双层不一致不会稳定存在:下一个读到服务层注释的人会相信它,并在一个假前提上继续写代码 —— 这比从来没声明过更坏。A 把属性收回一处;B 至少让两层说同一句话;C 留下「哪几个 arm 被门住」的规则,属性仍不在一处。

                          ② 真实业务拉力 —— 微弱,且方向偏 A。
                          B 保住的那个体验是:告诉用户「这条链接需要密码」—— 而该链接所在对象的分享开关是关的,即便密码正确也什么都取不到。那是在教用户开一扇已经砌死的门。没有测到任何消费者依赖这条消息;真正会遇到它的是拿着旧链接的正当用户,而他们无论如何都取不到内容,404 与 401 对他们的最终结果相同。

                          ③ 防 AI 编码错误 —— 强烈指向 A。
                          当前形状是个陷阱:agent 读 share-link-service.ts 那段注释会正确地推出「存在性预言已关闭」,据此写一个断言 404 的测试 —— 在服务层过、在 HTTP 层假。两层互相矛盾正是产出「自信而错误」代码的典型形状。⚠️ 附带的第二个陷阱:探针在 share-link-routes.tsruntime/src/domains/share-links.ts 各有一份重复实现,只改一处是可预期的失败模式,派工时必须点名两处。

                          ④ 创业阶段不增殖 —— 指向 A,明确反对 C。
                          A 不新增概念、不新增标签、不新增配置开关,只是把一次已有的读提前。C 会造出「第三类链接应答」和一条「哪些 arm 受门禁」的规则,是本轴要避免的增殖。

                          建议:A —— 探针整体门在 publicSharing.enabled 之后,两处同笔改。

                          回退:B,但不得沉默。 若维护者判断 401 提示对支持工作是承重的,那就选 B 并在两个探针处写下「路由层明知且有意接受该预言」,同时修正服务层注释使其不再宣称已关闭。⛔ 三个选项里唯一不可接受的是什么都不做:留着两层互相矛盾的注释,是本卡真正要消灭的东西。

                          ⚠️ 置信缺口(必录): 我没有测 objectui。若 share-link 查看器依赖 401 NEEDS_PASSWORD 这个状态码来渲染密码输入框,那么 A 会改变一条已发布的前端路径 —— 对关掉开关的对象的链接而言,用户看到的将从密码框变成「链接无效」。这条我读不到(跨仓,且本席不改代码),裁决前应由 repo:objectui 侧确认。这是本分析里唯一没有实测支撑的环节。

                          Re-check:git show origin/main:packages/plugins/plugin-sharing/src/share-link-routes.ts | sed -n '238,262p',以及 git show origin/main:packages/runtime/src/domains/share-links.ts | sed -n '145,163p'

                          Refs: #14033 · PR #14580 · #13857(同族的 eligibility 半边)· #14581 · #14582 · #14668(拆出的 changeset 措辞半边)

                          Generated by Claude Code

                          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

                              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
                              Skip to content

                              [Decision] The share-link route probe re-opens the existence oracle that share-link-service deliberately closed — a switched-off link with a password still answers 401 #14637

                              Description

                              @os-sales

                              Filed by the domain:services PM seat (session session_01AUF1NoViznQK32gqpK8wS8) from the non-blocking notes of the in-seat Clause-② contract review of PR #14580 (#14033) — round 1 note 5, adopted verbatim on 14033#issuecomment-5511376156. Re-measured by the triage seat at origin/main2aa8456.

                              Item 2 of the original filing (the changeset's "burst the log once" wording) is split to #14668 and is dispatchable now — it is not held behind this ruling.

                              The defect

                              resolveToken refuses a link whose object has publicSharing.enabled off, and the refusal is the undifferentiated null the #14033 ruling asked for — over HTTP a 404 INVALID_OR_EXPIRED, byte-identical to an unknown token, pinned at share-link-eligibility.test.ts:992-1022.

                              But the route's probe runs afterresolveToken returns null and answers from the row, with no knowledge of the object's block:

                              • packages/plugins/plugin-sharing/src/share-link-routes.ts401 NEEDS_PASSWORD / WRONG_PASSWORD for a row carrying password_hash; 401 SIGN_IN_REQUIRED for audience === 'signed_in' without a signed-in viewer
                              • packages/runtime/src/domains/share-links.tsa duplicated twin of the same probe, same arms, same codes

                              So for those two link shapes an anonymous caller can still tell a real-but-switched-off token from an unknown one, and a correct password on such a link answers WRONG_PASSWORD.

                              ⭐ Why this is more than "pre-existing, out of scope"

                              The service layer wrote the threat model down, in the same feature, immediately above the arm that closes it:

                              …for a caller who may hold nothing but a token, a distinguishable "sharing is off for this object" is an existence oracle, so the answer is the one revoked / expired / unknown / ineligible already give (over HTTP the generic 404).

                              The route above it then re-opens exactly that oracle for two of the three shapes. This is not a gap someone forgot to close — it is a security property that is stated in one layer and defeated in the layer above it, which is strictly worse than never having claimed it, because the next reader believes the comment.

                              It is genuinely pre-existing: the same shape applied to #13857's eligibility refusals and the reviewer classed it out of that PR's scope. What is new is that #14033 made the claim explicit in prose, so the contradiction is now readable.

                              What is NOT in question

                              Nothing in #14033's ruled behaviour: the gate, its placement before the record probe and the usage stamp, the three governed mint paths and the null-shape equality are all pinned, and the delta review PASSed with zero blocking findings. This card does not reopen any of that.

                              The shapes

                              • A · gate the probe on the standing policy — read publicSharing.enabled before the probe; when it is off, fall through to the generic 404 for every arm. Links on a switched-off object become uniformly indistinguishable from unknown tokens.
                              • B · leave it, and say so — keep the 401 affordance, and add a comment at both probe sites recording that the route layer deliberately accepts the oracle, so the service's comment stops being contradicted.
                              • C · gate only the two 401 arms, leave the 410 EXPIRED_OR_REVOKED arm answering from the row.

                              Common to A and C: the fix must land at both sites — the plugin route and the runtime dispatcher twin — or the oracle simply moves to whichever embedding uses the other one.

                              <!-- os-decision-facets -->

                              四棱分析(分诊席出具,供裁决)

                              ① 长期健全性(权重 ≥50%,主导本建议)—— 指向 A。
                              真正的缺陷不是「多答了一个 401」,而是同一个安全属性被写在一层、又被上一层拆掉。服务层把威胁模型逐字写下来了(「a distinguishable 'sharing is off for this object' is an existence oracle」),路由层照旧泄露。这种双层不一致不会稳定存在:下一个读到服务层注释的人会相信它,并在一个假前提上继续写代码 —— 这比从来没声明过更坏。A 把属性收回一处;B 至少让两层说同一句话;C 留下「哪几个 arm 被门住」的规则,属性仍不在一处。

                              ② 真实业务拉力 —— 微弱,且方向偏 A。
                              B 保住的那个体验是:告诉用户「这条链接需要密码」—— 而该链接所在对象的分享开关是关的,即便密码正确也什么都取不到。那是在教用户开一扇已经砌死的门。没有测到任何消费者依赖这条消息;真正会遇到它的是拿着旧链接的正当用户,而他们无论如何都取不到内容,404 与 401 对他们的最终结果相同。

                              ③ 防 AI 编码错误 —— 强烈指向 A。
                              当前形状是个陷阱:agent 读 share-link-service.ts 那段注释会正确地推出「存在性预言已关闭」,据此写一个断言 404 的测试 —— 在服务层过、在 HTTP 层假。两层互相矛盾正是产出「自信而错误」代码的典型形状。⚠️ 附带的第二个陷阱:探针在 share-link-routes.tsruntime/src/domains/share-links.ts 各有一份重复实现,只改一处是可预期的失败模式,派工时必须点名两处。

                              ④ 创业阶段不增殖 —— 指向 A,明确反对 C。
                              A 不新增概念、不新增标签、不新增配置开关,只是把一次已有的读提前。C 会造出「第三类链接应答」和一条「哪些 arm 受门禁」的规则,是本轴要避免的增殖。

                              建议:A —— 探针整体门在 publicSharing.enabled 之后,两处同笔改。

                              回退:B,但不得沉默。 若维护者判断 401 提示对支持工作是承重的,那就选 B 并在两个探针处写下「路由层明知且有意接受该预言」,同时修正服务层注释使其不再宣称已关闭。⛔ 三个选项里唯一不可接受的是什么都不做:留着两层互相矛盾的注释,是本卡真正要消灭的东西。

                              ⚠️ 置信缺口(必录): 我没有测 objectui。若 share-link 查看器依赖 401 NEEDS_PASSWORD 这个状态码来渲染密码输入框,那么 A 会改变一条已发布的前端路径 —— 对关掉开关的对象的链接而言,用户看到的将从密码框变成「链接无效」。这条我读不到(跨仓,且本席不改代码),裁决前应由 repo:objectui 侧确认。这是本分析里唯一没有实测支撑的环节。

                              Re-check:git show origin/main:packages/plugins/plugin-sharing/src/share-link-routes.ts | sed -n '238,262p',以及 git show origin/main:packages/runtime/src/domains/share-links.ts | sed -n '145,163p'

                              Refs: #14033 · PR #14580 · #13857(同族的 eligibility 半边)· #14581 · #14582 · #14668(拆出的 changeset 措辞半边)

                              Generated by Claude Code

                              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