v17 release notes: the #4366 entry states the svc:flow: audit label unqualified, and the #5494 entry later in the same page supersedes it — nothing connects them #14039

Description

@hotlong

Docs-only finding, filed unassigned. Surfaced by the Docs Drift Check on #14035, not ignored — that bot flagged a release-owned page, the guardrail says such a page is read-only and a genuine error should become an issue rather than an edit, so this is that issue.

content/docs/releases/ is release-owned and I did not touch it.

The two entries

Both are in content/docs/releases/v17.mdx, i.e. the same release:

Line 2072-2073 (#4366, under New capabilities (backend)):

…and a runAs: 'system' flow's writes are audited as svc:flow:<flowName> instead of "Unknown user" (#4366).

Line 2860-2861 (#5494):

runAs: 'system'create_record stamps all three ADR-0118 columns (#5494) — organization, owner and creator are non-NULL.

Neither is false on its own — the problem is what they say together

They describe two different things and each is accurate in isolation: #4366 is about the actor label, #5494 is about the stamped columns.

But the first is stated unqualified — "a runAs: 'system' flow's writes are audited as svc:flow:<flowName>" reads as the general rule for every system-elevated run. What actually ships (and what #5494 settled, later in the same release) is that the triggering user is carried through; svc:flow: is the fallback for a run that genuinely resolves no user, such as a schedule.

packages/services/service-automation/src/runtime-identity.ts:189 says it in as many words:

#5494 — elevation is not anonymity. When the trigger resolved a user …

So a reader working through v17's notes front to back meets the unqualified version ~800 lines before the entry that refines it, with nothing linking the two. A reader who stops at the first one comes away believing system elevation costs you the operator in the audit trail.

Why this is worth a card and not a shrug

This is the same false belief #14011 is fixing in the contract prose, in a page with considerably more readers than a .d.ts.

#14011 exists because that belief is load-bearing in the wrong direction: downstream it got written into a security adjudication as the explicit stop-condition — "if elevation erases the operator, stop and report a fork, because the requirement demands 谁修改了什么都要有日志可查". The correct design was one measurement away from being abandoned on a false premise. It survived only because the investigating agent measured instead of reading.

The contract-prose half is being corrected on #14035. This is the other place the same concept lives.

Suggested handling

The release page is a historical record, so the fix is not to rewrite the #4366 entry into what #5494 later made true — that would falsify what #4366 shipped. Two options that keep the record honest:

  1. Add a qualifier plus a pointer to the [automation/audit] runAs:'system' 流回写的审计行无归因(user_id/actor 双空),console 历史显示「未知用户」 #4366 entry — that svc:flow: is what a run resolving no user falls back to, and that Automation create_record under runAs:'system' inserts rows with owner_id/organization_id/created_by all NULL — records born untouchable even by admin #5494 (later in this same page) carries the triggering user through. Smallest change, keeps both entries accurate as written.
  2. Leave both and rely on the corrected contract prose now landing via docs(spec): correct AutomationContext.flowName's attribution prose — elevation decides authorization, not attribution #14035, on the view that release notes are per-change records and cross-linking them is not their job.

I lean to 1 because these two sit in the same release — this is not old notes describing an older behaviour, it is one page whose earlier row a later row on the same page supersedes. But release-note policy is the release process's call, not a downstream reporter's, so I am not proposing a PR.

Not a defect, for the record

The other row the drift check flagged on #14035content/docs/releases/v15.mdx:863 ("Flow-type actions now receive the caller's identity as a real AutomationContext (runAs: 'user' flows evaluate RLS as the caller)") — I checked and it is correct as written. It was listed because it names the AutomationContext symbol, which is precisely the precision-first behaviour the bot advertises. No action there.

Context: #14011, #14035. Filed from the downstream steedos-labs/hotcrm-heimao seat.

Metadata

Metadata

Assignees

Labels

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

    v17 release notes: the #4366 entry states the svc:flow: audit label unqualified, and the #5494 entry later in the same page supersedes it — nothing connects them #14039

    Description

    @hotlong

    Docs-only finding, filed unassigned. Surfaced by the Docs Drift Check on #14035, not ignored — that bot flagged a release-owned page, the guardrail says such a page is read-only and a genuine error should become an issue rather than an edit, so this is that issue.

    content/docs/releases/ is release-owned and I did not touch it.

    The two entries

    Both are in content/docs/releases/v17.mdx, i.e. the same release:

    Line 2072-2073 (#4366, under New capabilities (backend)):

    …and a runAs: 'system' flow's writes are audited as svc:flow:<flowName> instead of "Unknown user" (#4366).

    Line 2860-2861 (#5494):

    runAs: 'system'create_record stamps all three ADR-0118 columns (#5494) — organization, owner and creator are non-NULL.

    Neither is false on its own — the problem is what they say together

    They describe two different things and each is accurate in isolation: #4366 is about the actor label, #5494 is about the stamped columns.

    But the first is stated unqualified — "a runAs: 'system' flow's writes are audited as svc:flow:<flowName>" reads as the general rule for every system-elevated run. What actually ships (and what #5494 settled, later in the same release) is that the triggering user is carried through; svc:flow: is the fallback for a run that genuinely resolves no user, such as a schedule.

    packages/services/service-automation/src/runtime-identity.ts:189 says it in as many words:

    #5494 — elevation is not anonymity. When the trigger resolved a user …

    So a reader working through v17's notes front to back meets the unqualified version ~800 lines before the entry that refines it, with nothing linking the two. A reader who stops at the first one comes away believing system elevation costs you the operator in the audit trail.

    Why this is worth a card and not a shrug

    This is the same false belief #14011 is fixing in the contract prose, in a page with considerably more readers than a .d.ts.

    #14011 exists because that belief is load-bearing in the wrong direction: downstream it got written into a security adjudication as the explicit stop-condition — "if elevation erases the operator, stop and report a fork, because the requirement demands 谁修改了什么都要有日志可查". The correct design was one measurement away from being abandoned on a false premise. It survived only because the investigating agent measured instead of reading.

    The contract-prose half is being corrected on #14035. This is the other place the same concept lives.

    Suggested handling

    The release page is a historical record, so the fix is not to rewrite the #4366 entry into what #5494 later made true — that would falsify what #4366 shipped. Two options that keep the record honest:

    1. Add a qualifier plus a pointer to the [automation/audit] runAs:'system' 流回写的审计行无归因(user_id/actor 双空),console 历史显示「未知用户」 #4366 entry — that svc:flow: is what a run resolving no user falls back to, and that Automation create_record under runAs:'system' inserts rows with owner_id/organization_id/created_by all NULL — records born untouchable even by admin #5494 (later in this same page) carries the triggering user through. Smallest change, keeps both entries accurate as written.
    2. Leave both and rely on the corrected contract prose now landing via docs(spec): correct AutomationContext.flowName's attribution prose — elevation decides authorization, not attribution #14035, on the view that release notes are per-change records and cross-linking them is not their job.

    I lean to 1 because these two sit in the same release — this is not old notes describing an older behaviour, it is one page whose earlier row a later row on the same page supersedes. But release-note policy is the release process's call, not a downstream reporter's, so I am not proposing a PR.

    Not a defect, for the record

    The other row the drift check flagged on #14035content/docs/releases/v15.mdx:863 ("Flow-type actions now receive the caller's identity as a real AutomationContext (runAs: 'user' flows evaluate RLS as the caller)") — I checked and it is correct as written. It was listed because it names the AutomationContext symbol, which is precisely the precision-first behaviour the bot advertises. No action there.

    Context: #14011, #14035. Filed from the downstream steedos-labs/hotcrm-heimao seat.

    Metadata

    Metadata

    Assignees

    Labels

    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

      v17 release notes: the #4366 entry states the svc:flow: audit label unqualified, and the #5494 entry later in the same page supersedes it — nothing connects them #14039

      Description

      @hotlong

      Docs-only finding, filed unassigned. Surfaced by the Docs Drift Check on #14035, not ignored — that bot flagged a release-owned page, the guardrail says such a page is read-only and a genuine error should become an issue rather than an edit, so this is that issue.

      content/docs/releases/ is release-owned and I did not touch it.

      The two entries

      Both are in content/docs/releases/v17.mdx, i.e. the same release:

      Line 2072-2073 (#4366, under New capabilities (backend)):

      …and a runAs: 'system' flow's writes are audited as svc:flow:<flowName> instead of "Unknown user" (#4366).

      Line 2860-2861 (#5494):

      runAs: 'system'create_record stamps all three ADR-0118 columns (#5494) — organization, owner and creator are non-NULL.

      Neither is false on its own — the problem is what they say together

      They describe two different things and each is accurate in isolation: #4366 is about the actor label, #5494 is about the stamped columns.

      But the first is stated unqualified — "a runAs: 'system' flow's writes are audited as svc:flow:<flowName>" reads as the general rule for every system-elevated run. What actually ships (and what #5494 settled, later in the same release) is that the triggering user is carried through; svc:flow: is the fallback for a run that genuinely resolves no user, such as a schedule.

      packages/services/service-automation/src/runtime-identity.ts:189 says it in as many words:

      #5494 — elevation is not anonymity. When the trigger resolved a user …

      So a reader working through v17's notes front to back meets the unqualified version ~800 lines before the entry that refines it, with nothing linking the two. A reader who stops at the first one comes away believing system elevation costs you the operator in the audit trail.

      Why this is worth a card and not a shrug

      This is the same false belief #14011 is fixing in the contract prose, in a page with considerably more readers than a .d.ts.

      #14011 exists because that belief is load-bearing in the wrong direction: downstream it got written into a security adjudication as the explicit stop-condition — "if elevation erases the operator, stop and report a fork, because the requirement demands 谁修改了什么都要有日志可查". The correct design was one measurement away from being abandoned on a false premise. It survived only because the investigating agent measured instead of reading.

      The contract-prose half is being corrected on #14035. This is the other place the same concept lives.

      Suggested handling

      The release page is a historical record, so the fix is not to rewrite the #4366 entry into what #5494 later made true — that would falsify what #4366 shipped. Two options that keep the record honest:

      1. Add a qualifier plus a pointer to the [automation/audit] runAs:'system' 流回写的审计行无归因(user_id/actor 双空),console 历史显示「未知用户」 #4366 entry — that svc:flow: is what a run resolving no user falls back to, and that Automation create_record under runAs:'system' inserts rows with owner_id/organization_id/created_by all NULL — records born untouchable even by admin #5494 (later in this same page) carries the triggering user through. Smallest change, keeps both entries accurate as written.
      2. Leave both and rely on the corrected contract prose now landing via docs(spec): correct AutomationContext.flowName's attribution prose — elevation decides authorization, not attribution #14035, on the view that release notes are per-change records and cross-linking them is not their job.

      I lean to 1 because these two sit in the same release — this is not old notes describing an older behaviour, it is one page whose earlier row a later row on the same page supersedes. But release-note policy is the release process's call, not a downstream reporter's, so I am not proposing a PR.

      Not a defect, for the record

      The other row the drift check flagged on #14035content/docs/releases/v15.mdx:863 ("Flow-type actions now receive the caller's identity as a real AutomationContext (runAs: 'user' flows evaluate RLS as the caller)") — I checked and it is correct as written. It was listed because it names the AutomationContext symbol, which is precisely the precision-first behaviour the bot advertises. No action there.

      Context: #14011, #14035. Filed from the downstream steedos-labs/hotcrm-heimao seat.

      Metadata

      Metadata

      Assignees

      Labels

      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

        v17 release notes: the #4366 entry states the svc:flow: audit label unqualified, and the #5494 entry later in the same page supersedes it — nothing connects them #14039

        Description

        @hotlong

        Docs-only finding, filed unassigned. Surfaced by the Docs Drift Check on #14035, not ignored — that bot flagged a release-owned page, the guardrail says such a page is read-only and a genuine error should become an issue rather than an edit, so this is that issue.

        content/docs/releases/ is release-owned and I did not touch it.

        The two entries

        Both are in content/docs/releases/v17.mdx, i.e. the same release:

        Line 2072-2073 (#4366, under New capabilities (backend)):

        …and a runAs: 'system' flow's writes are audited as svc:flow:<flowName> instead of "Unknown user" (#4366).

        Line 2860-2861 (#5494):

        runAs: 'system'create_record stamps all three ADR-0118 columns (#5494) — organization, owner and creator are non-NULL.

        Neither is false on its own — the problem is what they say together

        They describe two different things and each is accurate in isolation: #4366 is about the actor label, #5494 is about the stamped columns.

        But the first is stated unqualified — "a runAs: 'system' flow's writes are audited as svc:flow:<flowName>" reads as the general rule for every system-elevated run. What actually ships (and what #5494 settled, later in the same release) is that the triggering user is carried through; svc:flow: is the fallback for a run that genuinely resolves no user, such as a schedule.

        packages/services/service-automation/src/runtime-identity.ts:189 says it in as many words:

        #5494 — elevation is not anonymity. When the trigger resolved a user …

        So a reader working through v17's notes front to back meets the unqualified version ~800 lines before the entry that refines it, with nothing linking the two. A reader who stops at the first one comes away believing system elevation costs you the operator in the audit trail.

        Why this is worth a card and not a shrug

        This is the same false belief #14011 is fixing in the contract prose, in a page with considerably more readers than a .d.ts.

        #14011 exists because that belief is load-bearing in the wrong direction: downstream it got written into a security adjudication as the explicit stop-condition — "if elevation erases the operator, stop and report a fork, because the requirement demands 谁修改了什么都要有日志可查". The correct design was one measurement away from being abandoned on a false premise. It survived only because the investigating agent measured instead of reading.

        The contract-prose half is being corrected on #14035. This is the other place the same concept lives.

        Suggested handling

        The release page is a historical record, so the fix is not to rewrite the #4366 entry into what #5494 later made true — that would falsify what #4366 shipped. Two options that keep the record honest:

        1. Add a qualifier plus a pointer to the [automation/audit] runAs:'system' 流回写的审计行无归因(user_id/actor 双空),console 历史显示「未知用户」 #4366 entry — that svc:flow: is what a run resolving no user falls back to, and that Automation create_record under runAs:'system' inserts rows with owner_id/organization_id/created_by all NULL — records born untouchable even by admin #5494 (later in this same page) carries the triggering user through. Smallest change, keeps both entries accurate as written.
        2. Leave both and rely on the corrected contract prose now landing via docs(spec): correct AutomationContext.flowName's attribution prose — elevation decides authorization, not attribution #14035, on the view that release notes are per-change records and cross-linking them is not their job.

        I lean to 1 because these two sit in the same release — this is not old notes describing an older behaviour, it is one page whose earlier row a later row on the same page supersedes. But release-note policy is the release process's call, not a downstream reporter's, so I am not proposing a PR.

        Not a defect, for the record

        The other row the drift check flagged on #14035content/docs/releases/v15.mdx:863 ("Flow-type actions now receive the caller's identity as a real AutomationContext (runAs: 'user' flows evaluate RLS as the caller)") — I checked and it is correct as written. It was listed because it names the AutomationContext symbol, which is precisely the precision-first behaviour the bot advertises. No action there.

        Context: #14011, #14035. Filed from the downstream steedos-labs/hotcrm-heimao seat.

        Metadata

        Metadata

        Assignees

        Labels

        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

          v17 release notes: the #4366 entry states the svc:flow: audit label unqualified, and the #5494 entry later in the same page supersedes it — nothing connects them #14039

          Description

          @hotlong

          Docs-only finding, filed unassigned. Surfaced by the Docs Drift Check on #14035, not ignored — that bot flagged a release-owned page, the guardrail says such a page is read-only and a genuine error should become an issue rather than an edit, so this is that issue.

          content/docs/releases/ is release-owned and I did not touch it.

          The two entries

          Both are in content/docs/releases/v17.mdx, i.e. the same release:

          Line 2072-2073 (#4366, under New capabilities (backend)):

          …and a runAs: 'system' flow's writes are audited as svc:flow:<flowName> instead of "Unknown user" (#4366).

          Line 2860-2861 (#5494):

          runAs: 'system'create_record stamps all three ADR-0118 columns (#5494) — organization, owner and creator are non-NULL.

          Neither is false on its own — the problem is what they say together

          They describe two different things and each is accurate in isolation: #4366 is about the actor label, #5494 is about the stamped columns.

          But the first is stated unqualified — "a runAs: 'system' flow's writes are audited as svc:flow:<flowName>" reads as the general rule for every system-elevated run. What actually ships (and what #5494 settled, later in the same release) is that the triggering user is carried through; svc:flow: is the fallback for a run that genuinely resolves no user, such as a schedule.

          packages/services/service-automation/src/runtime-identity.ts:189 says it in as many words:

          #5494 — elevation is not anonymity. When the trigger resolved a user …

          So a reader working through v17's notes front to back meets the unqualified version ~800 lines before the entry that refines it, with nothing linking the two. A reader who stops at the first one comes away believing system elevation costs you the operator in the audit trail.

          Why this is worth a card and not a shrug

          This is the same false belief #14011 is fixing in the contract prose, in a page with considerably more readers than a .d.ts.

          #14011 exists because that belief is load-bearing in the wrong direction: downstream it got written into a security adjudication as the explicit stop-condition — "if elevation erases the operator, stop and report a fork, because the requirement demands 谁修改了什么都要有日志可查". The correct design was one measurement away from being abandoned on a false premise. It survived only because the investigating agent measured instead of reading.

          The contract-prose half is being corrected on #14035. This is the other place the same concept lives.

          Suggested handling

          The release page is a historical record, so the fix is not to rewrite the #4366 entry into what #5494 later made true — that would falsify what #4366 shipped. Two options that keep the record honest:

          1. Add a qualifier plus a pointer to the [automation/audit] runAs:'system' 流回写的审计行无归因(user_id/actor 双空),console 历史显示「未知用户」 #4366 entry — that svc:flow: is what a run resolving no user falls back to, and that Automation create_record under runAs:'system' inserts rows with owner_id/organization_id/created_by all NULL — records born untouchable even by admin #5494 (later in this same page) carries the triggering user through. Smallest change, keeps both entries accurate as written.
          2. Leave both and rely on the corrected contract prose now landing via docs(spec): correct AutomationContext.flowName's attribution prose — elevation decides authorization, not attribution #14035, on the view that release notes are per-change records and cross-linking them is not their job.

          I lean to 1 because these two sit in the same release — this is not old notes describing an older behaviour, it is one page whose earlier row a later row on the same page supersedes. But release-note policy is the release process's call, not a downstream reporter's, so I am not proposing a PR.

          Not a defect, for the record

          The other row the drift check flagged on #14035content/docs/releases/v15.mdx:863 ("Flow-type actions now receive the caller's identity as a real AutomationContext (runAs: 'user' flows evaluate RLS as the caller)") — I checked and it is correct as written. It was listed because it names the AutomationContext symbol, which is precisely the precision-first behaviour the bot advertises. No action there.

          Context: #14011, #14035. Filed from the downstream steedos-labs/hotcrm-heimao seat.

          Metadata

          Metadata

          Assignees

          Labels

          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

            v17 release notes: the #4366 entry states the svc:flow: audit label unqualified, and the #5494 entry later in the same page supersedes it — nothing connects them #14039

            Description

            @hotlong

            Docs-only finding, filed unassigned. Surfaced by the Docs Drift Check on #14035, not ignored — that bot flagged a release-owned page, the guardrail says such a page is read-only and a genuine error should become an issue rather than an edit, so this is that issue.

            content/docs/releases/ is release-owned and I did not touch it.

            The two entries

            Both are in content/docs/releases/v17.mdx, i.e. the same release:

            Line 2072-2073 (#4366, under New capabilities (backend)):

            …and a runAs: 'system' flow's writes are audited as svc:flow:<flowName> instead of "Unknown user" (#4366).

            Line 2860-2861 (#5494):

            runAs: 'system'create_record stamps all three ADR-0118 columns (#5494) — organization, owner and creator are non-NULL.

            Neither is false on its own — the problem is what they say together

            They describe two different things and each is accurate in isolation: #4366 is about the actor label, #5494 is about the stamped columns.

            But the first is stated unqualified — "a runAs: 'system' flow's writes are audited as svc:flow:<flowName>" reads as the general rule for every system-elevated run. What actually ships (and what #5494 settled, later in the same release) is that the triggering user is carried through; svc:flow: is the fallback for a run that genuinely resolves no user, such as a schedule.

            packages/services/service-automation/src/runtime-identity.ts:189 says it in as many words:

            #5494 — elevation is not anonymity. When the trigger resolved a user …

            So a reader working through v17's notes front to back meets the unqualified version ~800 lines before the entry that refines it, with nothing linking the two. A reader who stops at the first one comes away believing system elevation costs you the operator in the audit trail.

            Why this is worth a card and not a shrug

            This is the same false belief #14011 is fixing in the contract prose, in a page with considerably more readers than a .d.ts.

            #14011 exists because that belief is load-bearing in the wrong direction: downstream it got written into a security adjudication as the explicit stop-condition — "if elevation erases the operator, stop and report a fork, because the requirement demands 谁修改了什么都要有日志可查". The correct design was one measurement away from being abandoned on a false premise. It survived only because the investigating agent measured instead of reading.

            The contract-prose half is being corrected on #14035. This is the other place the same concept lives.

            Suggested handling

            The release page is a historical record, so the fix is not to rewrite the #4366 entry into what #5494 later made true — that would falsify what #4366 shipped. Two options that keep the record honest:

            1. Add a qualifier plus a pointer to the [automation/audit] runAs:'system' 流回写的审计行无归因(user_id/actor 双空),console 历史显示「未知用户」 #4366 entry — that svc:flow: is what a run resolving no user falls back to, and that Automation create_record under runAs:'system' inserts rows with owner_id/organization_id/created_by all NULL — records born untouchable even by admin #5494 (later in this same page) carries the triggering user through. Smallest change, keeps both entries accurate as written.
            2. Leave both and rely on the corrected contract prose now landing via docs(spec): correct AutomationContext.flowName's attribution prose — elevation decides authorization, not attribution #14035, on the view that release notes are per-change records and cross-linking them is not their job.

            I lean to 1 because these two sit in the same release — this is not old notes describing an older behaviour, it is one page whose earlier row a later row on the same page supersedes. But release-note policy is the release process's call, not a downstream reporter's, so I am not proposing a PR.

            Not a defect, for the record

            The other row the drift check flagged on #14035content/docs/releases/v15.mdx:863 ("Flow-type actions now receive the caller's identity as a real AutomationContext (runAs: 'user' flows evaluate RLS as the caller)") — I checked and it is correct as written. It was listed because it names the AutomationContext symbol, which is precisely the precision-first behaviour the bot advertises. No action there.

            Context: #14011, #14035. Filed from the downstream steedos-labs/hotcrm-heimao seat.

            Metadata

            Metadata

            Assignees

            Labels

            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

              v17 release notes: the #4366 entry states the svc:flow: audit label unqualified, and the #5494 entry later in the same page supersedes it — nothing connects them #14039

              Description

              @hotlong

              Docs-only finding, filed unassigned. Surfaced by the Docs Drift Check on #14035, not ignored — that bot flagged a release-owned page, the guardrail says such a page is read-only and a genuine error should become an issue rather than an edit, so this is that issue.

              content/docs/releases/ is release-owned and I did not touch it.

              The two entries

              Both are in content/docs/releases/v17.mdx, i.e. the same release:

              Line 2072-2073 (#4366, under New capabilities (backend)):

              …and a runAs: 'system' flow's writes are audited as svc:flow:<flowName> instead of "Unknown user" (#4366).

              Line 2860-2861 (#5494):

              runAs: 'system'create_record stamps all three ADR-0118 columns (#5494) — organization, owner and creator are non-NULL.

              Neither is false on its own — the problem is what they say together

              They describe two different things and each is accurate in isolation: #4366 is about the actor label, #5494 is about the stamped columns.

              But the first is stated unqualified — "a runAs: 'system' flow's writes are audited as svc:flow:<flowName>" reads as the general rule for every system-elevated run. What actually ships (and what #5494 settled, later in the same release) is that the triggering user is carried through; svc:flow: is the fallback for a run that genuinely resolves no user, such as a schedule.

              packages/services/service-automation/src/runtime-identity.ts:189 says it in as many words:

              #5494 — elevation is not anonymity. When the trigger resolved a user …

              So a reader working through v17's notes front to back meets the unqualified version ~800 lines before the entry that refines it, with nothing linking the two. A reader who stops at the first one comes away believing system elevation costs you the operator in the audit trail.

              Why this is worth a card and not a shrug

              This is the same false belief #14011 is fixing in the contract prose, in a page with considerably more readers than a .d.ts.

              #14011 exists because that belief is load-bearing in the wrong direction: downstream it got written into a security adjudication as the explicit stop-condition — "if elevation erases the operator, stop and report a fork, because the requirement demands 谁修改了什么都要有日志可查". The correct design was one measurement away from being abandoned on a false premise. It survived only because the investigating agent measured instead of reading.

              The contract-prose half is being corrected on #14035. This is the other place the same concept lives.

              Suggested handling

              The release page is a historical record, so the fix is not to rewrite the #4366 entry into what #5494 later made true — that would falsify what #4366 shipped. Two options that keep the record honest:

              1. Add a qualifier plus a pointer to the [automation/audit] runAs:'system' 流回写的审计行无归因(user_id/actor 双空),console 历史显示「未知用户」 #4366 entry — that svc:flow: is what a run resolving no user falls back to, and that Automation create_record under runAs:'system' inserts rows with owner_id/organization_id/created_by all NULL — records born untouchable even by admin #5494 (later in this same page) carries the triggering user through. Smallest change, keeps both entries accurate as written.
              2. Leave both and rely on the corrected contract prose now landing via docs(spec): correct AutomationContext.flowName's attribution prose — elevation decides authorization, not attribution #14035, on the view that release notes are per-change records and cross-linking them is not their job.

              I lean to 1 because these two sit in the same release — this is not old notes describing an older behaviour, it is one page whose earlier row a later row on the same page supersedes. But release-note policy is the release process's call, not a downstream reporter's, so I am not proposing a PR.

              Not a defect, for the record

              The other row the drift check flagged on #14035content/docs/releases/v15.mdx:863 ("Flow-type actions now receive the caller's identity as a real AutomationContext (runAs: 'user' flows evaluate RLS as the caller)") — I checked and it is correct as written. It was listed because it names the AutomationContext symbol, which is precisely the precision-first behaviour the bot advertises. No action there.

              Context: #14011, #14035. Filed from the downstream steedos-labs/hotcrm-heimao seat.

              Metadata

              Metadata

              Assignees

              Labels

              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

                v17 release notes: the #4366 entry states the svc:flow: audit label unqualified, and the #5494 entry later in the same page supersedes it — nothing connects them #14039

                Description

                @hotlong

                Docs-only finding, filed unassigned. Surfaced by the Docs Drift Check on #14035, not ignored — that bot flagged a release-owned page, the guardrail says such a page is read-only and a genuine error should become an issue rather than an edit, so this is that issue.

                content/docs/releases/ is release-owned and I did not touch it.

                The two entries

                Both are in content/docs/releases/v17.mdx, i.e. the same release:

                Line 2072-2073 (#4366, under New capabilities (backend)):

                …and a runAs: 'system' flow's writes are audited as svc:flow:<flowName> instead of "Unknown user" (#4366).

                Line 2860-2861 (#5494):

                runAs: 'system'create_record stamps all three ADR-0118 columns (#5494) — organization, owner and creator are non-NULL.

                Neither is false on its own — the problem is what they say together

                They describe two different things and each is accurate in isolation: #4366 is about the actor label, #5494 is about the stamped columns.

                But the first is stated unqualified — "a runAs: 'system' flow's writes are audited as svc:flow:<flowName>" reads as the general rule for every system-elevated run. What actually ships (and what #5494 settled, later in the same release) is that the triggering user is carried through; svc:flow: is the fallback for a run that genuinely resolves no user, such as a schedule.

                packages/services/service-automation/src/runtime-identity.ts:189 says it in as many words:

                #5494 — elevation is not anonymity. When the trigger resolved a user …

                So a reader working through v17's notes front to back meets the unqualified version ~800 lines before the entry that refines it, with nothing linking the two. A reader who stops at the first one comes away believing system elevation costs you the operator in the audit trail.

                Why this is worth a card and not a shrug

                This is the same false belief #14011 is fixing in the contract prose, in a page with considerably more readers than a .d.ts.

                #14011 exists because that belief is load-bearing in the wrong direction: downstream it got written into a security adjudication as the explicit stop-condition — "if elevation erases the operator, stop and report a fork, because the requirement demands 谁修改了什么都要有日志可查". The correct design was one measurement away from being abandoned on a false premise. It survived only because the investigating agent measured instead of reading.

                The contract-prose half is being corrected on #14035. This is the other place the same concept lives.

                Suggested handling

                The release page is a historical record, so the fix is not to rewrite the #4366 entry into what #5494 later made true — that would falsify what #4366 shipped. Two options that keep the record honest:

                1. Add a qualifier plus a pointer to the [automation/audit] runAs:'system' 流回写的审计行无归因(user_id/actor 双空),console 历史显示「未知用户」 #4366 entry — that svc:flow: is what a run resolving no user falls back to, and that Automation create_record under runAs:'system' inserts rows with owner_id/organization_id/created_by all NULL — records born untouchable even by admin #5494 (later in this same page) carries the triggering user through. Smallest change, keeps both entries accurate as written.
                2. Leave both and rely on the corrected contract prose now landing via docs(spec): correct AutomationContext.flowName's attribution prose — elevation decides authorization, not attribution #14035, on the view that release notes are per-change records and cross-linking them is not their job.

                I lean to 1 because these two sit in the same release — this is not old notes describing an older behaviour, it is one page whose earlier row a later row on the same page supersedes. But release-note policy is the release process's call, not a downstream reporter's, so I am not proposing a PR.

                Not a defect, for the record

                The other row the drift check flagged on #14035content/docs/releases/v15.mdx:863 ("Flow-type actions now receive the caller's identity as a real AutomationContext (runAs: 'user' flows evaluate RLS as the caller)") — I checked and it is correct as written. It was listed because it names the AutomationContext symbol, which is precisely the precision-first behaviour the bot advertises. No action there.

                Context: #14011, #14035. Filed from the downstream steedos-labs/hotcrm-heimao seat.

                Metadata

                Metadata

                Assignees

                Labels

                Type

                No type

                Projects

                No projects

                  Milestone

                  No milestone

                  Relationships

                  None yet

                  Development

                  No branches or pull requests

                  Issue actions