From fba4a17fcc67982e2c9504c8fbea274487c06f35 Mon Sep 17 00:00:00 2001 From: John McLear Date: Sun, 17 May 2026 13:19:58 +0100 Subject: [PATCH] fix(API): hide SYSTEM_AUTHOR_ID from listAuthorsOfPad (#7793) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(API): exclude SYSTEM_AUTHOR_ID from listAuthorsOfPad Pad.SYSTEM_AUTHOR_ID ('a.etherpad-system') is the synthetic author Etherpad attributes inserts to when the HTTP API receives a call without authorId (setText, setHTML, appendText, the server-side import flows, and plugins like ep_post_data). It exists so the changeset's text and attribs stay in sync — without ANY author attribute, pad.atext drifts and clients fail setDocAText reconciliation when loading the pad. See Pad.ts:96-105 for the full rationale. That bookkeeping detail was leaking through listAuthorsOfPad: a pad whose only "contributor" is the system author still reported one authorID, which the existing tests in pad.ts and appendTextAuthor.ts (and presumably any caller that uses listAuthorsOfPad to count real users) treat as a real participant. Filter SYSTEM_AUTHOR_ID at the API surface so internal attribution stays internal. getAllAuthors() and downstream callers (copy, anonymize, atext verification) keep seeing the synthetic id — this only narrows the public listAuthorsOfPad response. Fixes #7785 Fixes #7790 Co-Authored-By: Claude Opus 4.7 (1M context) * docs(api): note that listAuthorsOfPad omits the system author Match the runtime behaviour from the previous commit — the synthetic 'a.etherpad-system' author used for unattributed inserts is filtered out of the listAuthorsOfPad response. Co-Authored-By: Claude Opus 4.7 (1M context) --------- Co-authored-by: Claude Opus 4.7 (1M context) --- doc/api/http_api.adoc | 2 ++ doc/api/http_api.md | 2 ++ src/node/db/API.ts | 8 +++++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/doc/api/http_api.adoc b/doc/api/http_api.adoc index 82313c54a..19c2839b4 100644 --- a/doc/api/http_api.adoc +++ b/doc/api/http_api.adoc @@ -654,6 +654,8 @@ _Example returns:_ returns an array of authors who contributed to this pad +The synthetic `a.etherpad-system` author (used internally when content is inserted without an explicit `authorId` — HTTP API `setText`/`appendText`/`setHTML` calls without `authorId`, server-side imports, plugins like `ep_post_data`) is omitted from the returned list. + _Example returns:_ * `{code: 0, message:"ok", data: {authorIDs : ["a.s8oes9dhwrvt0zif", "a.akf8finncvomlqva"]}` diff --git a/doc/api/http_api.md b/doc/api/http_api.md index 35437f23e..c9c57bfeb 100644 --- a/doc/api/http_api.md +++ b/doc/api/http_api.md @@ -698,6 +698,8 @@ return true of false returns an array of authors who contributed to this pad +The synthetic `a.etherpad-system` author (used internally when content is inserted without an explicit `authorId` — HTTP API `setText`/`appendText`/`setHTML` calls without `authorId`, server-side imports, plugins like `ep_post_data`) is omitted from the returned list. + *Example returns:* * `{code: 0, message:"ok", data: {authorIDs : ["a.s8oes9dhwrvt0zif", "a.akf8finncvomlqva"]}` * `{code: 1, message:"padID does not exist", data: null}` diff --git a/src/node/db/API.ts b/src/node/db/API.ts index 0af1836e3..68c953f28 100644 --- a/src/node/db/API.ts +++ b/src/node/db/API.ts @@ -855,7 +855,13 @@ Example returns: exports.listAuthorsOfPad = async (padID: string) => { // get the pad const pad = await getPadSafe(padID, true); - const authorIDs = pad.getAllAuthors(); + // Pad.SYSTEM_AUTHOR_ID is the synthetic author Etherpad attributes inserts to + // when no authorId is supplied (HTTP API setText/appendText/setHTML without + // authorId, server-side import flows, plugins like ep_post_data). It is an + // implementation detail of changeset bookkeeping, not a real contributor, so + // it should not surface through this public API. + const {Pad} = require('./Pad'); + const authorIDs = pad.getAllAuthors().filter((id: string) => id !== Pad.SYSTEM_AUTHOR_ID); return {authorIDs}; };