docs(security): publicSharing.enabled standing-policy paragraph (#14582) - #14746

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14582-public-sharing-standing-policy-docs
Sep 3, 2026
Merged

docs(security): publicSharing.enabled standing-policy paragraph (#14582)#14746
baozhoutao merged 1 commit into
mainfrom
claude/issue-14582-public-sharing-standing-policy-docs

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14582

What changed

Adds the sibling paragraph for the parent switch publicSharing.enabled (#14033) beside the existing "When eligibility is enforced" paragraph (#13608 / PR #13857) in content/docs/protocol/objectql/security.mdx's "Public Share Links" section, plus its upgrade-note callout in the same form. Item 2 of #14582 only — item 1 (system-context.mdx) already landed, item 3 (packages/spec/**) is #14703.

Placed after the eligibility paragraph + callout (not before): the triage comment asked for "the same shape one level up," which reads as recognition — a reader who has just understood the child predicate's paragraph should see the parent's paragraph and recognize the same shape, so the parent follows the child rather than pre-empting it.

The paragraph, verbatim

When publicSharing.enabled is off (#14033). The block's own switch is
the same standing-policy shape as eligibility above, one level up: it too
is held at every redemption, not only at mint. Turning it off stops every
existing link on the object immediately, with no revocation step to
remember; turning it back on restores them, with no link needing to be
re-minted. Turning the block off silences everything inside it —
eligibility is not evaluated, redactFields is not computed — so the
bypass some callers have at mint (a late schema scan, or a system context)
buys only the mint: it still succeeds while the block is off, but what it
mints does not resolve until the block is enabled. What an anonymous holder
sees is the same "invalid or expired" answer eligibility already gives;
the readable reason is written to the server log, never to the response.

Upgrade note. (Callout) Before this, publicSharing.enabled gated only the mint —
once a link was issued it kept resolving after the object's switch was
turned off. Deployments upgrading across that change can feel it: links
that used to keep serving after enabled was flipped off now stop
immediately, and resume as soon as it is flipped back on. That is the
intent — the alternative was a declared switch the platform did not hold —
but there is no way to keep an already-minted link serving through the
object being switched off; the object must stay opted in for its links to
serve.

Behaviour verified on base, packages/plugins/plugin-sharing/src/share-link-service.ts

  • (a) off ⇒ existing links stop resolving, held at every redemption:resolveToken, packages/plugins/plugin-sharing/src/share-link-service.ts:697if (!policy.enabled) { ...; return null; }, preceded by the [#14033] comment block starting at :652 ("publicSharing.enabled is a STANDING policy — held here, at every redemption, not only at mint").
  • (b) on ⇒ resolves again, no re-mint: same comment block, :663-669 ("a block that is off stops every existing token on it — retroactively... and re-enabling the block restores them. Not a revocation: no row moves.").
  • (c) bypass mints but does not serve:createLink's opt-in gate, :449if (!policy.enabled && !this.permissive && !context.isSystem) { throw ...; } — only refuses the mint when neither the permissive bypass nor a system context applies; the [#14033] Mint ONLY doc comment at :346-355 states the corollary explicitly ("a link minted under this bypass while the block is off does not resolve until the block is enabled").

All three match what the PR body describes; no discrepancy found.

Scope discipline

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands content/docs/protocol/objectql/security.mdx derived 29 families (re-derived clean, non-stale, at merged HEAD 96574ba46). All 29 were run (--ran reconciliation: 29 derived, 29 run, 0 UNRUN). 25 passed for real (exit 0); the remaining 4 are NOT MEASURED — each is a build-prerequisite gap in a fresh worktree unrelated to this docs-only diff, not a finding:

  • pnpm --filter @objectstack/lint run check:doc-formula-expressions / check:doc-security-posture@objectstack/lint's own build fails in this worktree on a missing @objectstack/sdui-parser type declaration, a pre-existing package-graph gap this diff does not touch.
  • pnpm --filter @objectstack/spec run check:skill-examples — corpus-wide TS type-check across all doc/skill code blocks; blocked here on @objectstack/client-react's dist not carrying .d.ts in this worktree, unrelated to this prose-only change.
  • node scripts/check-test-completeness.mjs — requires a saved turbo run test log CI produces; the gate's own guidance names this NOT MEASURED (not a red) when run standalone.

The directly relevant gate, pnpm --filter @objectstack/spec run check:docs (renders/validates the docs tree, including this file), passed for real once @objectstack/spec was built (exit 0). CI runs the full farm and will get a real build for the other four.

Labels

skip-changeset requested — docs-only prose change, no package publishes from this diff.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV


Generated by Claude Code

Item 2 of #14582 (follow-up to #14033 / PR #14580, split from #14033's
docs surfaces that PR #14580 could not touch). The "Public Share Links"
section documented the child predicate (eligibility, #13608) as a
standing policy held at every redemption, but not the parent switch
publicSharing.enabled — #14033 made that switch the same shape: held at
every redemption, not only at mint. Adds the sibling paragraph plus its
upgrade-note callout, placed after the eligibility paragraph so a reader
who has already understood the child predicate recognises the parent's
paragraph as the same shape one level up.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/s documentation Improvements or additions to documentation labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 23:54
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 89a156aSep 3, 2026
37 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14582-public-sharing-standing-policy-docs branch September 3, 2026 01:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: state the standing-policy semantics of publicSharing.enabled on the three prose surfaces #14580 could not touch (follow-up to #14033)

2 participants

@baozhoutao@claude
, '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

docs(security): publicSharing.enabled standing-policy paragraph (#14582) - #14746

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14582-public-sharing-standing-policy-docs
Sep 3, 2026
Merged

docs(security): publicSharing.enabled standing-policy paragraph (#14582)#14746
baozhoutao merged 1 commit into
mainfrom
claude/issue-14582-public-sharing-standing-policy-docs

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14582

What changed

Adds the sibling paragraph for the parent switch publicSharing.enabled (#14033) beside the existing "When eligibility is enforced" paragraph (#13608 / PR #13857) in content/docs/protocol/objectql/security.mdx's "Public Share Links" section, plus its upgrade-note callout in the same form. Item 2 of #14582 only — item 1 (system-context.mdx) already landed, item 3 (packages/spec/**) is #14703.

Placed after the eligibility paragraph + callout (not before): the triage comment asked for "the same shape one level up," which reads as recognition — a reader who has just understood the child predicate's paragraph should see the parent's paragraph and recognize the same shape, so the parent follows the child rather than pre-empting it.

The paragraph, verbatim

When publicSharing.enabled is off (#14033). The block's own switch is
the same standing-policy shape as eligibility above, one level up: it too
is held at every redemption, not only at mint. Turning it off stops every
existing link on the object immediately, with no revocation step to
remember; turning it back on restores them, with no link needing to be
re-minted. Turning the block off silences everything inside it —
eligibility is not evaluated, redactFields is not computed — so the
bypass some callers have at mint (a late schema scan, or a system context)
buys only the mint: it still succeeds while the block is off, but what it
mints does not resolve until the block is enabled. What an anonymous holder
sees is the same "invalid or expired" answer eligibility already gives;
the readable reason is written to the server log, never to the response.

Upgrade note. (Callout) Before this, publicSharing.enabled gated only the mint —
once a link was issued it kept resolving after the object's switch was
turned off. Deployments upgrading across that change can feel it: links
that used to keep serving after enabled was flipped off now stop
immediately, and resume as soon as it is flipped back on. That is the
intent — the alternative was a declared switch the platform did not hold —
but there is no way to keep an already-minted link serving through the
object being switched off; the object must stay opted in for its links to
serve.

Behaviour verified on base, packages/plugins/plugin-sharing/src/share-link-service.ts

  • (a) off ⇒ existing links stop resolving, held at every redemption:resolveToken, packages/plugins/plugin-sharing/src/share-link-service.ts:697if (!policy.enabled) { ...; return null; }, preceded by the [#14033] comment block starting at :652 ("publicSharing.enabled is a STANDING policy — held here, at every redemption, not only at mint").
  • (b) on ⇒ resolves again, no re-mint: same comment block, :663-669 ("a block that is off stops every existing token on it — retroactively... and re-enabling the block restores them. Not a revocation: no row moves.").
  • (c) bypass mints but does not serve:createLink's opt-in gate, :449if (!policy.enabled && !this.permissive && !context.isSystem) { throw ...; } — only refuses the mint when neither the permissive bypass nor a system context applies; the [#14033] Mint ONLY doc comment at :346-355 states the corollary explicitly ("a link minted under this bypass while the block is off does not resolve until the block is enabled").

All three match what the PR body describes; no discrepancy found.

Scope discipline

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands content/docs/protocol/objectql/security.mdx derived 29 families (re-derived clean, non-stale, at merged HEAD 96574ba46). All 29 were run (--ran reconciliation: 29 derived, 29 run, 0 UNRUN). 25 passed for real (exit 0); the remaining 4 are NOT MEASURED — each is a build-prerequisite gap in a fresh worktree unrelated to this docs-only diff, not a finding:

  • pnpm --filter @objectstack/lint run check:doc-formula-expressions / check:doc-security-posture@objectstack/lint's own build fails in this worktree on a missing @objectstack/sdui-parser type declaration, a pre-existing package-graph gap this diff does not touch.
  • pnpm --filter @objectstack/spec run check:skill-examples — corpus-wide TS type-check across all doc/skill code blocks; blocked here on @objectstack/client-react's dist not carrying .d.ts in this worktree, unrelated to this prose-only change.
  • node scripts/check-test-completeness.mjs — requires a saved turbo run test log CI produces; the gate's own guidance names this NOT MEASURED (not a red) when run standalone.

The directly relevant gate, pnpm --filter @objectstack/spec run check:docs (renders/validates the docs tree, including this file), passed for real once @objectstack/spec was built (exit 0). CI runs the full farm and will get a real build for the other four.

Labels

skip-changeset requested — docs-only prose change, no package publishes from this diff.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV


Generated by Claude Code

Item 2 of #14582 (follow-up to #14033 / PR #14580, split from #14033's
docs surfaces that PR #14580 could not touch). The "Public Share Links"
section documented the child predicate (eligibility, #13608) as a
standing policy held at every redemption, but not the parent switch
publicSharing.enabled — #14033 made that switch the same shape: held at
every redemption, not only at mint. Adds the sibling paragraph plus its
upgrade-note callout, placed after the eligibility paragraph so a reader
who has already understood the child predicate recognises the parent's
paragraph as the same shape one level up.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/s documentation Improvements or additions to documentation labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 23:54
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 89a156aSep 3, 2026
37 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14582-public-sharing-standing-policy-docs branch September 3, 2026 01:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: state the standing-policy semantics of publicSharing.enabled on the three prose surfaces #14580 could not touch (follow-up to #14033)

2 participants

@baozhoutao@claude
, '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

docs(security): publicSharing.enabled standing-policy paragraph (#14582) - #14746

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14582-public-sharing-standing-policy-docs
Sep 3, 2026
Merged

docs(security): publicSharing.enabled standing-policy paragraph (#14582)#14746
baozhoutao merged 1 commit into
mainfrom
claude/issue-14582-public-sharing-standing-policy-docs

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14582

What changed

Adds the sibling paragraph for the parent switch publicSharing.enabled (#14033) beside the existing "When eligibility is enforced" paragraph (#13608 / PR #13857) in content/docs/protocol/objectql/security.mdx's "Public Share Links" section, plus its upgrade-note callout in the same form. Item 2 of #14582 only — item 1 (system-context.mdx) already landed, item 3 (packages/spec/**) is #14703.

Placed after the eligibility paragraph + callout (not before): the triage comment asked for "the same shape one level up," which reads as recognition — a reader who has just understood the child predicate's paragraph should see the parent's paragraph and recognize the same shape, so the parent follows the child rather than pre-empting it.

The paragraph, verbatim

When publicSharing.enabled is off (#14033). The block's own switch is
the same standing-policy shape as eligibility above, one level up: it too
is held at every redemption, not only at mint. Turning it off stops every
existing link on the object immediately, with no revocation step to
remember; turning it back on restores them, with no link needing to be
re-minted. Turning the block off silences everything inside it —
eligibility is not evaluated, redactFields is not computed — so the
bypass some callers have at mint (a late schema scan, or a system context)
buys only the mint: it still succeeds while the block is off, but what it
mints does not resolve until the block is enabled. What an anonymous holder
sees is the same "invalid or expired" answer eligibility already gives;
the readable reason is written to the server log, never to the response.

Upgrade note. (Callout) Before this, publicSharing.enabled gated only the mint —
once a link was issued it kept resolving after the object's switch was
turned off. Deployments upgrading across that change can feel it: links
that used to keep serving after enabled was flipped off now stop
immediately, and resume as soon as it is flipped back on. That is the
intent — the alternative was a declared switch the platform did not hold —
but there is no way to keep an already-minted link serving through the
object being switched off; the object must stay opted in for its links to
serve.

Behaviour verified on base, packages/plugins/plugin-sharing/src/share-link-service.ts

  • (a) off ⇒ existing links stop resolving, held at every redemption:resolveToken, packages/plugins/plugin-sharing/src/share-link-service.ts:697if (!policy.enabled) { ...; return null; }, preceded by the [#14033] comment block starting at :652 ("publicSharing.enabled is a STANDING policy — held here, at every redemption, not only at mint").
  • (b) on ⇒ resolves again, no re-mint: same comment block, :663-669 ("a block that is off stops every existing token on it — retroactively... and re-enabling the block restores them. Not a revocation: no row moves.").
  • (c) bypass mints but does not serve:createLink's opt-in gate, :449if (!policy.enabled && !this.permissive && !context.isSystem) { throw ...; } — only refuses the mint when neither the permissive bypass nor a system context applies; the [#14033] Mint ONLY doc comment at :346-355 states the corollary explicitly ("a link minted under this bypass while the block is off does not resolve until the block is enabled").

All three match what the PR body describes; no discrepancy found.

Scope discipline

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands content/docs/protocol/objectql/security.mdx derived 29 families (re-derived clean, non-stale, at merged HEAD 96574ba46). All 29 were run (--ran reconciliation: 29 derived, 29 run, 0 UNRUN). 25 passed for real (exit 0); the remaining 4 are NOT MEASURED — each is a build-prerequisite gap in a fresh worktree unrelated to this docs-only diff, not a finding:

  • pnpm --filter @objectstack/lint run check:doc-formula-expressions / check:doc-security-posture@objectstack/lint's own build fails in this worktree on a missing @objectstack/sdui-parser type declaration, a pre-existing package-graph gap this diff does not touch.
  • pnpm --filter @objectstack/spec run check:skill-examples — corpus-wide TS type-check across all doc/skill code blocks; blocked here on @objectstack/client-react's dist not carrying .d.ts in this worktree, unrelated to this prose-only change.
  • node scripts/check-test-completeness.mjs — requires a saved turbo run test log CI produces; the gate's own guidance names this NOT MEASURED (not a red) when run standalone.

The directly relevant gate, pnpm --filter @objectstack/spec run check:docs (renders/validates the docs tree, including this file), passed for real once @objectstack/spec was built (exit 0). CI runs the full farm and will get a real build for the other four.

Labels

skip-changeset requested — docs-only prose change, no package publishes from this diff.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV


Generated by Claude Code

Item 2 of #14582 (follow-up to #14033 / PR #14580, split from #14033's
docs surfaces that PR #14580 could not touch). The "Public Share Links"
section documented the child predicate (eligibility, #13608) as a
standing policy held at every redemption, but not the parent switch
publicSharing.enabled — #14033 made that switch the same shape: held at
every redemption, not only at mint. Adds the sibling paragraph plus its
upgrade-note callout, placed after the eligibility paragraph so a reader
who has already understood the child predicate recognises the parent's
paragraph as the same shape one level up.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/s documentation Improvements or additions to documentation labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 23:54
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 89a156aSep 3, 2026
37 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14582-public-sharing-standing-policy-docs branch September 3, 2026 01:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: state the standing-policy semantics of publicSharing.enabled on the three prose surfaces #14580 could not touch (follow-up to #14033)

2 participants

@baozhoutao@claude
, '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

docs(security): publicSharing.enabled standing-policy paragraph (#14582) - #14746

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14582-public-sharing-standing-policy-docs
Sep 3, 2026
Merged

docs(security): publicSharing.enabled standing-policy paragraph (#14582)#14746
baozhoutao merged 1 commit into
mainfrom
claude/issue-14582-public-sharing-standing-policy-docs

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14582

What changed

Adds the sibling paragraph for the parent switch publicSharing.enabled (#14033) beside the existing "When eligibility is enforced" paragraph (#13608 / PR #13857) in content/docs/protocol/objectql/security.mdx's "Public Share Links" section, plus its upgrade-note callout in the same form. Item 2 of #14582 only — item 1 (system-context.mdx) already landed, item 3 (packages/spec/**) is #14703.

Placed after the eligibility paragraph + callout (not before): the triage comment asked for "the same shape one level up," which reads as recognition — a reader who has just understood the child predicate's paragraph should see the parent's paragraph and recognize the same shape, so the parent follows the child rather than pre-empting it.

The paragraph, verbatim

When publicSharing.enabled is off (#14033). The block's own switch is
the same standing-policy shape as eligibility above, one level up: it too
is held at every redemption, not only at mint. Turning it off stops every
existing link on the object immediately, with no revocation step to
remember; turning it back on restores them, with no link needing to be
re-minted. Turning the block off silences everything inside it —
eligibility is not evaluated, redactFields is not computed — so the
bypass some callers have at mint (a late schema scan, or a system context)
buys only the mint: it still succeeds while the block is off, but what it
mints does not resolve until the block is enabled. What an anonymous holder
sees is the same "invalid or expired" answer eligibility already gives;
the readable reason is written to the server log, never to the response.

Upgrade note. (Callout) Before this, publicSharing.enabled gated only the mint —
once a link was issued it kept resolving after the object's switch was
turned off. Deployments upgrading across that change can feel it: links
that used to keep serving after enabled was flipped off now stop
immediately, and resume as soon as it is flipped back on. That is the
intent — the alternative was a declared switch the platform did not hold —
but there is no way to keep an already-minted link serving through the
object being switched off; the object must stay opted in for its links to
serve.

Behaviour verified on base, packages/plugins/plugin-sharing/src/share-link-service.ts

  • (a) off ⇒ existing links stop resolving, held at every redemption:resolveToken, packages/plugins/plugin-sharing/src/share-link-service.ts:697if (!policy.enabled) { ...; return null; }, preceded by the [#14033] comment block starting at :652 ("publicSharing.enabled is a STANDING policy — held here, at every redemption, not only at mint").
  • (b) on ⇒ resolves again, no re-mint: same comment block, :663-669 ("a block that is off stops every existing token on it — retroactively... and re-enabling the block restores them. Not a revocation: no row moves.").
  • (c) bypass mints but does not serve:createLink's opt-in gate, :449if (!policy.enabled && !this.permissive && !context.isSystem) { throw ...; } — only refuses the mint when neither the permissive bypass nor a system context applies; the [#14033] Mint ONLY doc comment at :346-355 states the corollary explicitly ("a link minted under this bypass while the block is off does not resolve until the block is enabled").

All three match what the PR body describes; no discrepancy found.

Scope discipline

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands content/docs/protocol/objectql/security.mdx derived 29 families (re-derived clean, non-stale, at merged HEAD 96574ba46). All 29 were run (--ran reconciliation: 29 derived, 29 run, 0 UNRUN). 25 passed for real (exit 0); the remaining 4 are NOT MEASURED — each is a build-prerequisite gap in a fresh worktree unrelated to this docs-only diff, not a finding:

  • pnpm --filter @objectstack/lint run check:doc-formula-expressions / check:doc-security-posture@objectstack/lint's own build fails in this worktree on a missing @objectstack/sdui-parser type declaration, a pre-existing package-graph gap this diff does not touch.
  • pnpm --filter @objectstack/spec run check:skill-examples — corpus-wide TS type-check across all doc/skill code blocks; blocked here on @objectstack/client-react's dist not carrying .d.ts in this worktree, unrelated to this prose-only change.
  • node scripts/check-test-completeness.mjs — requires a saved turbo run test log CI produces; the gate's own guidance names this NOT MEASURED (not a red) when run standalone.

The directly relevant gate, pnpm --filter @objectstack/spec run check:docs (renders/validates the docs tree, including this file), passed for real once @objectstack/spec was built (exit 0). CI runs the full farm and will get a real build for the other four.

Labels

skip-changeset requested — docs-only prose change, no package publishes from this diff.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV


Generated by Claude Code

Item 2 of #14582 (follow-up to #14033 / PR #14580, split from #14033's
docs surfaces that PR #14580 could not touch). The "Public Share Links"
section documented the child predicate (eligibility, #13608) as a
standing policy held at every redemption, but not the parent switch
publicSharing.enabled — #14033 made that switch the same shape: held at
every redemption, not only at mint. Adds the sibling paragraph plus its
upgrade-note callout, placed after the eligibility paragraph so a reader
who has already understood the child predicate recognises the parent's
paragraph as the same shape one level up.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/s documentation Improvements or additions to documentation labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 23:54
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 89a156aSep 3, 2026
37 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14582-public-sharing-standing-policy-docs branch September 3, 2026 01:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: state the standing-policy semantics of publicSharing.enabled on the three prose surfaces #14580 could not touch (follow-up to #14033)

2 participants

@baozhoutao@claude
, '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

docs(security): publicSharing.enabled standing-policy paragraph (#14582) - #14746

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14582-public-sharing-standing-policy-docs
Sep 3, 2026
Merged

docs(security): publicSharing.enabled standing-policy paragraph (#14582)#14746
baozhoutao merged 1 commit into
mainfrom
claude/issue-14582-public-sharing-standing-policy-docs

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14582

What changed

Adds the sibling paragraph for the parent switch publicSharing.enabled (#14033) beside the existing "When eligibility is enforced" paragraph (#13608 / PR #13857) in content/docs/protocol/objectql/security.mdx's "Public Share Links" section, plus its upgrade-note callout in the same form. Item 2 of #14582 only — item 1 (system-context.mdx) already landed, item 3 (packages/spec/**) is #14703.

Placed after the eligibility paragraph + callout (not before): the triage comment asked for "the same shape one level up," which reads as recognition — a reader who has just understood the child predicate's paragraph should see the parent's paragraph and recognize the same shape, so the parent follows the child rather than pre-empting it.

The paragraph, verbatim

When publicSharing.enabled is off (#14033). The block's own switch is
the same standing-policy shape as eligibility above, one level up: it too
is held at every redemption, not only at mint. Turning it off stops every
existing link on the object immediately, with no revocation step to
remember; turning it back on restores them, with no link needing to be
re-minted. Turning the block off silences everything inside it —
eligibility is not evaluated, redactFields is not computed — so the
bypass some callers have at mint (a late schema scan, or a system context)
buys only the mint: it still succeeds while the block is off, but what it
mints does not resolve until the block is enabled. What an anonymous holder
sees is the same "invalid or expired" answer eligibility already gives;
the readable reason is written to the server log, never to the response.

Upgrade note. (Callout) Before this, publicSharing.enabled gated only the mint —
once a link was issued it kept resolving after the object's switch was
turned off. Deployments upgrading across that change can feel it: links
that used to keep serving after enabled was flipped off now stop
immediately, and resume as soon as it is flipped back on. That is the
intent — the alternative was a declared switch the platform did not hold —
but there is no way to keep an already-minted link serving through the
object being switched off; the object must stay opted in for its links to
serve.

Behaviour verified on base, packages/plugins/plugin-sharing/src/share-link-service.ts

  • (a) off ⇒ existing links stop resolving, held at every redemption:resolveToken, packages/plugins/plugin-sharing/src/share-link-service.ts:697if (!policy.enabled) { ...; return null; }, preceded by the [#14033] comment block starting at :652 ("publicSharing.enabled is a STANDING policy — held here, at every redemption, not only at mint").
  • (b) on ⇒ resolves again, no re-mint: same comment block, :663-669 ("a block that is off stops every existing token on it — retroactively... and re-enabling the block restores them. Not a revocation: no row moves.").
  • (c) bypass mints but does not serve:createLink's opt-in gate, :449if (!policy.enabled && !this.permissive && !context.isSystem) { throw ...; } — only refuses the mint when neither the permissive bypass nor a system context applies; the [#14033] Mint ONLY doc comment at :346-355 states the corollary explicitly ("a link minted under this bypass while the block is off does not resolve until the block is enabled").

All three match what the PR body describes; no discrepancy found.

Scope discipline

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands content/docs/protocol/objectql/security.mdx derived 29 families (re-derived clean, non-stale, at merged HEAD 96574ba46). All 29 were run (--ran reconciliation: 29 derived, 29 run, 0 UNRUN). 25 passed for real (exit 0); the remaining 4 are NOT MEASURED — each is a build-prerequisite gap in a fresh worktree unrelated to this docs-only diff, not a finding:

  • pnpm --filter @objectstack/lint run check:doc-formula-expressions / check:doc-security-posture@objectstack/lint's own build fails in this worktree on a missing @objectstack/sdui-parser type declaration, a pre-existing package-graph gap this diff does not touch.
  • pnpm --filter @objectstack/spec run check:skill-examples — corpus-wide TS type-check across all doc/skill code blocks; blocked here on @objectstack/client-react's dist not carrying .d.ts in this worktree, unrelated to this prose-only change.
  • node scripts/check-test-completeness.mjs — requires a saved turbo run test log CI produces; the gate's own guidance names this NOT MEASURED (not a red) when run standalone.

The directly relevant gate, pnpm --filter @objectstack/spec run check:docs (renders/validates the docs tree, including this file), passed for real once @objectstack/spec was built (exit 0). CI runs the full farm and will get a real build for the other four.

Labels

skip-changeset requested — docs-only prose change, no package publishes from this diff.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV


Generated by Claude Code

Item 2 of #14582 (follow-up to #14033 / PR #14580, split from #14033's
docs surfaces that PR #14580 could not touch). The "Public Share Links"
section documented the child predicate (eligibility, #13608) as a
standing policy held at every redemption, but not the parent switch
publicSharing.enabled — #14033 made that switch the same shape: held at
every redemption, not only at mint. Adds the sibling paragraph plus its
upgrade-note callout, placed after the eligibility paragraph so a reader
who has already understood the child predicate recognises the parent's
paragraph as the same shape one level up.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/s documentation Improvements or additions to documentation labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 23:54
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 89a156aSep 3, 2026
37 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14582-public-sharing-standing-policy-docs branch September 3, 2026 01:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: state the standing-policy semantics of publicSharing.enabled on the three prose surfaces #14580 could not touch (follow-up to #14033)

2 participants

@baozhoutao@claude
, '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

docs(security): publicSharing.enabled standing-policy paragraph (#14582) - #14746

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14582-public-sharing-standing-policy-docs
Sep 3, 2026
Merged

docs(security): publicSharing.enabled standing-policy paragraph (#14582)#14746
baozhoutao merged 1 commit into
mainfrom
claude/issue-14582-public-sharing-standing-policy-docs

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14582

What changed

Adds the sibling paragraph for the parent switch publicSharing.enabled (#14033) beside the existing "When eligibility is enforced" paragraph (#13608 / PR #13857) in content/docs/protocol/objectql/security.mdx's "Public Share Links" section, plus its upgrade-note callout in the same form. Item 2 of #14582 only — item 1 (system-context.mdx) already landed, item 3 (packages/spec/**) is #14703.

Placed after the eligibility paragraph + callout (not before): the triage comment asked for "the same shape one level up," which reads as recognition — a reader who has just understood the child predicate's paragraph should see the parent's paragraph and recognize the same shape, so the parent follows the child rather than pre-empting it.

The paragraph, verbatim

When publicSharing.enabled is off (#14033). The block's own switch is
the same standing-policy shape as eligibility above, one level up: it too
is held at every redemption, not only at mint. Turning it off stops every
existing link on the object immediately, with no revocation step to
remember; turning it back on restores them, with no link needing to be
re-minted. Turning the block off silences everything inside it —
eligibility is not evaluated, redactFields is not computed — so the
bypass some callers have at mint (a late schema scan, or a system context)
buys only the mint: it still succeeds while the block is off, but what it
mints does not resolve until the block is enabled. What an anonymous holder
sees is the same "invalid or expired" answer eligibility already gives;
the readable reason is written to the server log, never to the response.

Upgrade note. (Callout) Before this, publicSharing.enabled gated only the mint —
once a link was issued it kept resolving after the object's switch was
turned off. Deployments upgrading across that change can feel it: links
that used to keep serving after enabled was flipped off now stop
immediately, and resume as soon as it is flipped back on. That is the
intent — the alternative was a declared switch the platform did not hold —
but there is no way to keep an already-minted link serving through the
object being switched off; the object must stay opted in for its links to
serve.

Behaviour verified on base, packages/plugins/plugin-sharing/src/share-link-service.ts

  • (a) off ⇒ existing links stop resolving, held at every redemption:resolveToken, packages/plugins/plugin-sharing/src/share-link-service.ts:697if (!policy.enabled) { ...; return null; }, preceded by the [#14033] comment block starting at :652 ("publicSharing.enabled is a STANDING policy — held here, at every redemption, not only at mint").
  • (b) on ⇒ resolves again, no re-mint: same comment block, :663-669 ("a block that is off stops every existing token on it — retroactively... and re-enabling the block restores them. Not a revocation: no row moves.").
  • (c) bypass mints but does not serve:createLink's opt-in gate, :449if (!policy.enabled && !this.permissive && !context.isSystem) { throw ...; } — only refuses the mint when neither the permissive bypass nor a system context applies; the [#14033] Mint ONLY doc comment at :346-355 states the corollary explicitly ("a link minted under this bypass while the block is off does not resolve until the block is enabled").

All three match what the PR body describes; no discrepancy found.

Scope discipline

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands content/docs/protocol/objectql/security.mdx derived 29 families (re-derived clean, non-stale, at merged HEAD 96574ba46). All 29 were run (--ran reconciliation: 29 derived, 29 run, 0 UNRUN). 25 passed for real (exit 0); the remaining 4 are NOT MEASURED — each is a build-prerequisite gap in a fresh worktree unrelated to this docs-only diff, not a finding:

  • pnpm --filter @objectstack/lint run check:doc-formula-expressions / check:doc-security-posture@objectstack/lint's own build fails in this worktree on a missing @objectstack/sdui-parser type declaration, a pre-existing package-graph gap this diff does not touch.
  • pnpm --filter @objectstack/spec run check:skill-examples — corpus-wide TS type-check across all doc/skill code blocks; blocked here on @objectstack/client-react's dist not carrying .d.ts in this worktree, unrelated to this prose-only change.
  • node scripts/check-test-completeness.mjs — requires a saved turbo run test log CI produces; the gate's own guidance names this NOT MEASURED (not a red) when run standalone.

The directly relevant gate, pnpm --filter @objectstack/spec run check:docs (renders/validates the docs tree, including this file), passed for real once @objectstack/spec was built (exit 0). CI runs the full farm and will get a real build for the other four.

Labels

skip-changeset requested — docs-only prose change, no package publishes from this diff.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV


Generated by Claude Code

Item 2 of #14582 (follow-up to #14033 / PR #14580, split from #14033's
docs surfaces that PR #14580 could not touch). The "Public Share Links"
section documented the child predicate (eligibility, #13608) as a
standing policy held at every redemption, but not the parent switch
publicSharing.enabled — #14033 made that switch the same shape: held at
every redemption, not only at mint. Adds the sibling paragraph plus its
upgrade-note callout, placed after the eligibility paragraph so a reader
who has already understood the child predicate recognises the parent's
paragraph as the same shape one level up.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/s documentation Improvements or additions to documentation labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 23:54
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 89a156aSep 3, 2026
37 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14582-public-sharing-standing-policy-docs branch September 3, 2026 01:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: state the standing-policy semantics of publicSharing.enabled on the three prose surfaces #14580 could not touch (follow-up to #14033)

2 participants

@baozhoutao@claude
, '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

docs(security): publicSharing.enabled standing-policy paragraph (#14582) - #14746

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14582-public-sharing-standing-policy-docs
Sep 3, 2026
Merged

docs(security): publicSharing.enabled standing-policy paragraph (#14582)#14746
baozhoutao merged 1 commit into
mainfrom
claude/issue-14582-public-sharing-standing-policy-docs

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14582

What changed

Adds the sibling paragraph for the parent switch publicSharing.enabled (#14033) beside the existing "When eligibility is enforced" paragraph (#13608 / PR #13857) in content/docs/protocol/objectql/security.mdx's "Public Share Links" section, plus its upgrade-note callout in the same form. Item 2 of #14582 only — item 1 (system-context.mdx) already landed, item 3 (packages/spec/**) is #14703.

Placed after the eligibility paragraph + callout (not before): the triage comment asked for "the same shape one level up," which reads as recognition — a reader who has just understood the child predicate's paragraph should see the parent's paragraph and recognize the same shape, so the parent follows the child rather than pre-empting it.

The paragraph, verbatim

When publicSharing.enabled is off (#14033). The block's own switch is
the same standing-policy shape as eligibility above, one level up: it too
is held at every redemption, not only at mint. Turning it off stops every
existing link on the object immediately, with no revocation step to
remember; turning it back on restores them, with no link needing to be
re-minted. Turning the block off silences everything inside it —
eligibility is not evaluated, redactFields is not computed — so the
bypass some callers have at mint (a late schema scan, or a system context)
buys only the mint: it still succeeds while the block is off, but what it
mints does not resolve until the block is enabled. What an anonymous holder
sees is the same "invalid or expired" answer eligibility already gives;
the readable reason is written to the server log, never to the response.

Upgrade note. (Callout) Before this, publicSharing.enabled gated only the mint —
once a link was issued it kept resolving after the object's switch was
turned off. Deployments upgrading across that change can feel it: links
that used to keep serving after enabled was flipped off now stop
immediately, and resume as soon as it is flipped back on. That is the
intent — the alternative was a declared switch the platform did not hold —
but there is no way to keep an already-minted link serving through the
object being switched off; the object must stay opted in for its links to
serve.

Behaviour verified on base, packages/plugins/plugin-sharing/src/share-link-service.ts

  • (a) off ⇒ existing links stop resolving, held at every redemption:resolveToken, packages/plugins/plugin-sharing/src/share-link-service.ts:697if (!policy.enabled) { ...; return null; }, preceded by the [#14033] comment block starting at :652 ("publicSharing.enabled is a STANDING policy — held here, at every redemption, not only at mint").
  • (b) on ⇒ resolves again, no re-mint: same comment block, :663-669 ("a block that is off stops every existing token on it — retroactively... and re-enabling the block restores them. Not a revocation: no row moves.").
  • (c) bypass mints but does not serve:createLink's opt-in gate, :449if (!policy.enabled && !this.permissive && !context.isSystem) { throw ...; } — only refuses the mint when neither the permissive bypass nor a system context applies; the [#14033] Mint ONLY doc comment at :346-355 states the corollary explicitly ("a link minted under this bypass while the block is off does not resolve until the block is enabled").

All three match what the PR body describes; no discrepancy found.

Scope discipline

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands content/docs/protocol/objectql/security.mdx derived 29 families (re-derived clean, non-stale, at merged HEAD 96574ba46). All 29 were run (--ran reconciliation: 29 derived, 29 run, 0 UNRUN). 25 passed for real (exit 0); the remaining 4 are NOT MEASURED — each is a build-prerequisite gap in a fresh worktree unrelated to this docs-only diff, not a finding:

  • pnpm --filter @objectstack/lint run check:doc-formula-expressions / check:doc-security-posture@objectstack/lint's own build fails in this worktree on a missing @objectstack/sdui-parser type declaration, a pre-existing package-graph gap this diff does not touch.
  • pnpm --filter @objectstack/spec run check:skill-examples — corpus-wide TS type-check across all doc/skill code blocks; blocked here on @objectstack/client-react's dist not carrying .d.ts in this worktree, unrelated to this prose-only change.
  • node scripts/check-test-completeness.mjs — requires a saved turbo run test log CI produces; the gate's own guidance names this NOT MEASURED (not a red) when run standalone.

The directly relevant gate, pnpm --filter @objectstack/spec run check:docs (renders/validates the docs tree, including this file), passed for real once @objectstack/spec was built (exit 0). CI runs the full farm and will get a real build for the other four.

Labels

skip-changeset requested — docs-only prose change, no package publishes from this diff.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV


Generated by Claude Code

Item 2 of #14582 (follow-up to #14033 / PR #14580, split from #14033's
docs surfaces that PR #14580 could not touch). The "Public Share Links"
section documented the child predicate (eligibility, #13608) as a
standing policy held at every redemption, but not the parent switch
publicSharing.enabled — #14033 made that switch the same shape: held at
every redemption, not only at mint. Adds the sibling paragraph plus its
upgrade-note callout, placed after the eligibility paragraph so a reader
who has already understood the child predicate recognises the parent's
paragraph as the same shape one level up.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/s documentation Improvements or additions to documentation labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 23:54
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 89a156aSep 3, 2026
37 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14582-public-sharing-standing-policy-docs branch September 3, 2026 01:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: state the standing-policy semantics of publicSharing.enabled on the three prose surfaces #14580 could not touch (follow-up to #14033)

2 participants

@baozhoutao@claude
, '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

docs(security): publicSharing.enabled standing-policy paragraph (#14582) - #14746

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14582-public-sharing-standing-policy-docs
Sep 3, 2026
Merged

docs(security): publicSharing.enabled standing-policy paragraph (#14582)#14746
baozhoutao merged 1 commit into
mainfrom
claude/issue-14582-public-sharing-standing-policy-docs

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#14582

What changed

Adds the sibling paragraph for the parent switch publicSharing.enabled (#14033) beside the existing "When eligibility is enforced" paragraph (#13608 / PR #13857) in content/docs/protocol/objectql/security.mdx's "Public Share Links" section, plus its upgrade-note callout in the same form. Item 2 of #14582 only — item 1 (system-context.mdx) already landed, item 3 (packages/spec/**) is #14703.

Placed after the eligibility paragraph + callout (not before): the triage comment asked for "the same shape one level up," which reads as recognition — a reader who has just understood the child predicate's paragraph should see the parent's paragraph and recognize the same shape, so the parent follows the child rather than pre-empting it.

The paragraph, verbatim

When publicSharing.enabled is off (#14033). The block's own switch is
the same standing-policy shape as eligibility above, one level up: it too
is held at every redemption, not only at mint. Turning it off stops every
existing link on the object immediately, with no revocation step to
remember; turning it back on restores them, with no link needing to be
re-minted. Turning the block off silences everything inside it —
eligibility is not evaluated, redactFields is not computed — so the
bypass some callers have at mint (a late schema scan, or a system context)
buys only the mint: it still succeeds while the block is off, but what it
mints does not resolve until the block is enabled. What an anonymous holder
sees is the same "invalid or expired" answer eligibility already gives;
the readable reason is written to the server log, never to the response.

Upgrade note. (Callout) Before this, publicSharing.enabled gated only the mint —
once a link was issued it kept resolving after the object's switch was
turned off. Deployments upgrading across that change can feel it: links
that used to keep serving after enabled was flipped off now stop
immediately, and resume as soon as it is flipped back on. That is the
intent — the alternative was a declared switch the platform did not hold —
but there is no way to keep an already-minted link serving through the
object being switched off; the object must stay opted in for its links to
serve.

Behaviour verified on base, packages/plugins/plugin-sharing/src/share-link-service.ts

  • (a) off ⇒ existing links stop resolving, held at every redemption:resolveToken, packages/plugins/plugin-sharing/src/share-link-service.ts:697if (!policy.enabled) { ...; return null; }, preceded by the [#14033] comment block starting at :652 ("publicSharing.enabled is a STANDING policy — held here, at every redemption, not only at mint").
  • (b) on ⇒ resolves again, no re-mint: same comment block, :663-669 ("a block that is off stops every existing token on it — retroactively... and re-enabling the block restores them. Not a revocation: no row moves.").
  • (c) bypass mints but does not serve:createLink's opt-in gate, :449if (!policy.enabled && !this.permissive && !context.isSystem) { throw ...; } — only refuses the mint when neither the permissive bypass nor a system context applies; the [#14033] Mint ONLY doc comment at :346-355 states the corollary explicitly ("a link minted under this bypass while the block is off does not resolve until the block is enabled").

All three match what the PR body describes; no discrepancy found.

Scope discipline

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands content/docs/protocol/objectql/security.mdx derived 29 families (re-derived clean, non-stale, at merged HEAD 96574ba46). All 29 were run (--ran reconciliation: 29 derived, 29 run, 0 UNRUN). 25 passed for real (exit 0); the remaining 4 are NOT MEASURED — each is a build-prerequisite gap in a fresh worktree unrelated to this docs-only diff, not a finding:

  • pnpm --filter @objectstack/lint run check:doc-formula-expressions / check:doc-security-posture@objectstack/lint's own build fails in this worktree on a missing @objectstack/sdui-parser type declaration, a pre-existing package-graph gap this diff does not touch.
  • pnpm --filter @objectstack/spec run check:skill-examples — corpus-wide TS type-check across all doc/skill code blocks; blocked here on @objectstack/client-react's dist not carrying .d.ts in this worktree, unrelated to this prose-only change.
  • node scripts/check-test-completeness.mjs — requires a saved turbo run test log CI produces; the gate's own guidance names this NOT MEASURED (not a red) when run standalone.

The directly relevant gate, pnpm --filter @objectstack/spec run check:docs (renders/validates the docs tree, including this file), passed for real once @objectstack/spec was built (exit 0). CI runs the full farm and will get a real build for the other four.

Labels

skip-changeset requested — docs-only prose change, no package publishes from this diff.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV


Generated by Claude Code

Item 2 of #14582 (follow-up to #14033 / PR #14580, split from #14033's
docs surfaces that PR #14580 could not touch). The "Public Share Links"
section documented the child predicate (eligibility, #13608) as a
standing policy held at every redemption, but not the parent switch
publicSharing.enabled — #14033 made that switch the same shape: held at
every redemption, not only at mint. Adds the sibling paragraph plus its
upgrade-note callout, placed after the eligibility paragraph so a reader
who has already understood the child predicate recognises the parent's
paragraph as the same shape one level up.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/s documentation Improvements or additions to documentation labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 23:54
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 89a156aSep 3, 2026
37 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14582-public-sharing-standing-policy-docs branch September 3, 2026 01:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: state the standing-policy semantics of publicSharing.enabled on the three prose surfaces #14580 could not touch (follow-up to #14033)

2 participants

@baozhoutao@claude