docs(ospo): community health rollout v2 — LICENSE, README, agents.md, health files - #97
Conversation
DeepDiver1975
left a comment
There was a problem hiding this comment.
Code review
Ten findings, all correctness/consistency — none of them block a merge on their own, but two are wrong information in files this PR itself touches.
What I verified rather than took on trust
- All five "verbatim" community-health files are byte-identical to
owncloud/docs-main(sha256 match), andLICENSEis byte-identical to the canonicalhttps://www.gnu.org/licenses/agpl-3.0.txt(661 lines, zero diff). - The action pin is genuine:
48f256284bd46cdaab1048c3721360e808335d50is exactly tagv6.1.1, which is the current latest release. - Every factual claim in
agents.mdabout repository structure holds up against the tree: the 7content/*products, the 4antora-extensions/, the 2asciidoc-extensions/,ui/supplemental/,sync/,test/, all npm script names, Node 22 in CI, default branchmain. - Antora's
start_pathscovercontent/*only, so the new root-level Markdown is genuinely outside the site build. npm ci --dry-runstill exits 0 after thepackage.jsonchange — addinglicensedoes not desync the lockfile.- Pages is CNAME'd to
doc.owncloud.comand the only required status check isbuild, so the new workflow is advisory rather than gating. - Of the links added across these files, only the YesWeHack one is broken;
security.owncloud.com, Element/Matrix, discussions,owncloud.com/contribute/*,kiteworks.com/opensourceandcontact-usall return 200.
Worth fixing before merge
README.md:11advertiseshttps://doc.owncloud.comwhilesite.yml:6still setssite.urlto the personal fork host. Canonical links andsitemap.xmlboth derive fromsite.url, so the published site would point search engines at a URL that isn't the publish target. The follow-up PR the description mentions should land together with this line.README.md:19andagents.md:28disagree about the branch model (mastervsmain;mainis correct).
Smaller but real
agents.md:39documentsnpm teststandalone; run that way, 4 of 17 tests silently skip — and they are thego.php/latestalias / redirect-target integration checks.- The YesWeHack bug bounty URL in
SECURITY.md:11andREADME.md:205is a 404, and no such programme exists on YesWeHack at all. package.json:5uses the deprecated SPDX IDAGPL-3.0rather thanAGPL-3.0-only/-or-later— relevant given thereuse lintpilot named as the next step.lint-pr-title.yml:5drops the defaultreopenedtrigger and adds a no-opsynchronize.lint-pr-title.yml:13has noconcurrencygroup, so a superseded failing run can overwrite a passing status.README.md:197states an Actions policy stricter thanagents.md:57— and the workflow this PR adds fails the stricter wording.LICENSEis the unmodified FSF template with no copyright holder named anywhere in the repository, which AGPL §4/§5 assume is present on conveyance.
Deliberately not raised
The SPDX-License-Identifier: Apache-2.0 header in .github/CODEOWNERS (already flagged in the description; generator-owned and not fixable here), the stale /owncloud-docs-monorepo prefix in test/go-redirect.test.js and package-lock.json's name field (pre-existing, outside this diff), and README's "Watch for release notifications" on a repository that publishes no releases (template boilerplate with no failure mode).
🤖 Review generated with Claude Code
| UI repo) with **one monorepo** built by Antora. | ||
|
|
||
| Live (GitHub Pages): https://deepdiver1975.github.io/owncloud-docs-monorepo/ | ||
| Live (GitHub Pages): https://doc.owncloud.com |
There was a problem hiding this comment.
The README now advertises a URL that site.yml does not publish to.
This line points at https://doc.owncloud.com, but site.yml:6 still sets site.url to https://deepdiver1975.github.io/owncloud-docs-monorepo. Antora derives both the <link rel="canonical"> on every page and the sitemap.xml entries (via antora-extensions/sitemap-cleanup.js) from site.url — so every page served from doc.owncloud.com would declare the personal fork host as canonical, and the sitemap would advertise only fork URLs. That is the classic way to get a production site deindexed in favour of a URL that isn't the publish target.
The PR description defers the site.yml change to a follow-up, but this line is what turns a latent mismatch into a published promise, so the two should land together. Setting site.url: https://doc.owncloud.com is safe with respect to the go.php compatibility layer — resolveGoPhp derives its base path from location.pathname at runtime, so the redirects survive any base-path change.
| Live (GitHub Pages): https://deepdiver1975.github.io/owncloud-docs-monorepo/ | ||
| Live (GitHub Pages): https://doc.owncloud.com | ||
|
|
||
| ## What changed vs. the legacy setup |
There was a problem hiding this comment.
This section (the table row at line 19) still documents the branch model as "master only", contradicting agents.md:28 added in this same PR.
agents.md:28 says Branching: main, and main is in fact this repository's default branch. A contributor — or an AI agent, which is precisely the audience agents.md targets — who trusts the README will try to branch from or target master, which does not exist here. Two files changed by one PR should not disagree about something this basic.
| ``` | ||
| git commit -s -S -m "your commit message" | ||
| ``` | ||
| - **GitHub Actions Policy**: Workflows may only use actions that are (a) owned by `owncloud`, (b) created by GitHub (`actions/*`), or (c) verified in the GitHub Marketplace. |
There was a problem hiding this comment.
This Actions policy is stricter than the one in agents.md:57, and the workflow added by this same PR fails it.
Here the allowed set is (a) owned by owncloud, (b) actions/*, or (c) verified in the GitHub Marketplace. agents.md:57 adds a fourth clause — "or verified by the ownCloud Maintainers".
amannn/action-semantic-pull-request, added in .github/workflows/lint-pr-title.yml by this PR, is owned by a personal account (amannn, API "type": "User"), and personal accounts cannot hold the Marketplace verified-creator badge — that badge is only issued to organizations. So under this wording the new workflow is non-compliant with the policy introduced alongside it.
The action is already used roughly 50 times across the owncloud org, so the intent is clearly the agents.md wording. Align this line to agents.md rather than the other way round.
| **<https://security.owncloud.com>** | ||
|
|
||
| You can also report vulnerabilities through our YesWeHack bug bounty program: | ||
| **<https://yeswehack.com/programs/owncloud-bug-bounty-program>** |
There was a problem hiding this comment.
This bug bounty URL is dead — it returns HTTP 404, and the programme does not exist.
https://yeswehack.com/programs/owncloud-bug-bounty-program responds 404. I also enumerated YesWeHack's full public programme list through their API (63 programmes across 2 pages): there is no ownCloud or Kiteworks programme at all, so this is not a renamed slug.
SECURITY.md is the document GitHub surfaces as the canonical place to report a vulnerability, which makes a 404 here the worst place to have one — a researcher who hits it may simply give up, or fall back to opening a public issue, exactly what the line above forbids. README.md:205 carries the same dead link.
The same URL appears in owncloud/core, ocis and android, so the durable fix is an OSPO-level sweep; but since this PR is what introduces it into this repository, it should not ship as-is. Every other link in these new files checks out (security.owncloud.com, Element/Matrix, discussions, owncloud.com/contribute/*, kiteworks.com/opensource, contact-us all return 200) — this is the only broken one.
|
|
||
| Report vulnerabilities at **<https://security.owncloud.com>** -- see [SECURITY.md](SECURITY.md). | ||
|
|
||
| Bug bounty: [YesWeHack ownCloud Program](https://yeswehack.com/programs/owncloud-bug-bounty-program) |
There was a problem hiding this comment.
Same dead YesWeHack link as SECURITY.md:11 — HTTP 404, and no such programme exists on YesWeHack. See that thread for the detail; both occurrences need the same treatment.
| "description": "The ownCloud documentation (consolidated monorepo)", | ||
| "homepage": "https://github.com/DeepDiver1975/owncloud-docs-monorepo#readme", | ||
| "homepage": "https://github.com/owncloud/docs.owncloud.com#readme", | ||
| "license": "AGPL-3.0", |
There was a problem hiding this comment.
AGPL-3.0 is a deprecated SPDX identifier (isDeprecatedLicenseId: true since the SPDX 3.0 licence list). The current forms are AGPL-3.0-only and AGPL-3.0-or-later.
This matters more than usual in a PR whose stated purpose is licence compliance:
- SBOM and licence scanners — including
reuse lint, the exact pilot the PR description names as the next step — warn or fail on deprecated identifiers. - The deprecated form is silent on the "or later" question, which the LICENSE appendix explicitly raises ("either version 3 of the License, or (at your option) any later version"). Picking
-onlyor-or-laterrecords a decision instead of leaving it ambiguous in machine-readable metadata.
Worth choosing deliberately rather than inheriting the legacy string.
|
|
||
| on: | ||
| pull_request: | ||
| types: |
There was a problem hiding this comment.
This explicit types: list drops the default reopened and adds a synchronize that cannot change the outcome.
pull_request defaults to [opened, synchronize, reopened]. Overriding it with [opened, edited, synchronize] means closing and reopening a PR without touching its title produces no run at all, so the check silently disappears from the PR rather than carrying over. Conversely synchronize re-lints the title on every single push, where the title by definition has not changed.
Harmless today, because the docs.owncloud.com-status-checks ruleset requires only build. But if this context is ever added to that ruleset, a reopened PR sits permanently pending with no way to trigger the workflow short of an empty commit.
types: [opened, edited, reopened]| permissions: | ||
| pull-requests: read | ||
|
|
||
| jobs: |
There was a problem hiding this comment.
No concurrency group, so overlapping runs can leave a stale red check.
Edit a PR title twice in quick succession — a typo fix immediately after the first attempt — and two runs race. If the earlier, failing run reports last, it overwrites the passing status and the PR shows a red "Lint PR title" against a title that is now valid, until someone re-runs it by hand.
ci.yml in this repository already scopes concurrency per ref (with a comment explaining exactly this), so the convention is established:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true| npm run build # Antora build + Pagefind search index | ||
|
|
||
| # Test | ||
| npm test # node --test test/*.test.js |
There was a problem hiding this comment.
Documenting npm test standalone hides the fact that four of the tests silently skip themselves without a prior build.
Run on a clean checkout, npm test reports 13 pass, 0 fail — and 4 skipped, via t.skip('public/ not built …'). The four that skip are exactly the integration checks that make this suite worth having:
- every
go.phpmapping resolves to a target that exists - every multi-version component root redirects to its latest version
- the redirect target page itself exists
CI happens to be safe because ci.yml runs npm run antora before npm test. But an agent following this file locally sees a green "0 fail" and can ship a broken latest alias or a dead redirect target believing it was tested — a false negative that reads as a pass.
Since the audience of this file is specifically agents acting on it without further context, the dependency should be explicit:
npm run antora && npm test # the redirect tests skip themselves unless public/ exists| @@ -0,0 +1,661 @@ | |||
| GNU AFFERO GENERAL PUBLIC LICENSE | |||
There was a problem hiding this comment.
This is the unmodified FSF template, and no copyright holder is stated anywhere in the repository.
I verified this file is byte-identical to https://www.gnu.org/licenses/agpl-3.0.txt (661 lines, zero diff) — correct as the licence text, but the template deliberately leaves the holder to the project. AGPL §4 and §5 require appropriate copyright notices to be preserved when the work is conveyed, and the built site is conveyed to every visitor. With no Copyright (C) <years> ownCloud GmbH / Kiteworks line in the repository or on the published pages, this AGPL-licensed documentation ships with no attributable holder — and the -only vs -or-later question raised on package.json stays unanswerable, because only the holder can decide it.
Verbatim-matching owncloud/docs-main means the gap is inherited rather than introduced here, and naming the holder and the year range is a call for legal/OSPO rather than a reviewer. But it is the one substantive hole left in an otherwise complete compliance rollout, and it is probably cheapest to close in the PR that establishes the licence.
… health files
This repo superseded the archived per-product docs-* repos but never received
the OSPO community health rollout v2 that the rest of the org got on
2026-06-22 (docs-main 82dbaaf, docs-server dc082e0). owncloud/.github holds no
org-default community health files, so nothing was inherited — most visibly,
a public repo publishing AGPL-3.0-derived documentation with no LICENSE at all.
Added, verbatim from owncloud/docs-main (byte-identical across the docs family):
LICENSE GNU AGPL v3, matching docs-main/docs-server/docs-webui,
the upstream sources this content was synced from
CONTRIBUTING.md -> owncloud.com/contribute/
CODE_OF_CONDUCT.md -> owncloud.com/contribute/code-of-conduct/
SECURITY.md -> security.owncloud.com + YesWeHack bug bounty
SUPPORT.md enterprise / discussions / Matrix / docs channels
Adapted to this monorepo rather than copied:
agents.md docs-main's section order, retargeted to the Antora
monorepo: content/<product>/<version>/ folders, Pagefind,
the local extension dirs, npm scripts, Node 22, main
branch, and the versions-are-folders / mirror-retired
constraints
README.md OSPO v2 marker, licence + OSPO badges, and the template
sections (Community & Support, Contributing, Security,
License, About the OSPO, Apache-2.0 migration) appended
around the existing monorepo design notes, which are kept
Also added .github/workflows/lint-pr-title.yml from docs-main, with an explicit
`permissions: pull-requests: read` to match ci.yml's style. The repo already
uses Conventional Commit PR titles and squash-merges, but nothing enforced it.
Two stale references to the prototype's personal fork are corrected on the way
past: README's live URL and package.json's homepage now point at
owncloud/docs.owncloud.com, and package.json declares "license": "AGPL-3.0"
consistently with the new LICENSE.
Deliberately not included: REUSE.toml/LICENSES/ and SPDX headers (still a
three-repo pilot org-wide), GOVERNANCE.md and MAINTAINERS.md (present in no
ownCloud repo), a DCO file (enforced by rulesets), .github/settings.yml
(superseded by owncloud/admin safe-settings), and issue/PR templates (only
pre-OSPO copies exist, referencing retired labels and dead URLs).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
17012fb to
a36b7ed
Compare
- README claimed the branch model is `master` only; the default branch is `main`, as agents.md already stated in the same change. - README's GitHub Actions policy omitted the "verified by the ownCloud Maintainers" clause that agents.md carries. Under the narrower wording the lint-pr-title workflow added alongside it was non-compliant with the policy introduced in the same change, since amannn is a personal account and cannot hold a Marketplace verified-creator badge. - The YesWeHack bug bounty URL 404s and no such programme exists on YesWeHack, so both occurrences are dropped; security.owncloud.com remains the reporting route SECURITY.md points at. - agents.md documented `npm test` standalone, but 4 of the redirect/alias tests skip themselves unless public/ has been built, which reads as a pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
AGPL-3.0 is deprecated in the SPDX licence list, and scanners -- including the reuse lint pilot this rollout is heading towards -- warn or fail on deprecated identifiers. AGPL-3.0-or-later matches the identifier owncloud/core declares in its composer.json. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
The explicit types list dropped the default `reopened`, so closing and reopening a PR left the check absent rather than carrying it over, and added a `synchronize` that cannot change a PR title. Without a concurrency group two quick title edits race, and a superseded failing run finishing last leaves a red check on a title that is already valid. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
Review findings addressedPushed as three commits on top of
Already fixed upstreamThe #98's commit message also independently confirms the Decisions worth a second opinion
The bug bounty reference was removed, not redirected. I could not find any replacement: enumerating YesWeHack's full public programme list via their API (63 programmes, 2 pages) returns no ownCloud or Kiteworks programme, so this is not a renamed slug. Left open deliberately
🤖 Generated with Claude Code |
dj4oC
left a comment
There was a problem hiding this comment.
Docs/config-only PR (community health rollout) — reviewed for accuracy of every factual claim in the PR body against the live repo, sibling repos, and upstream sources, rather than just reading the diff.
Critical — please fix before merge
SECURITY.md is missing the YesWeHack bug-bounty paragraph.
The PR description's file table lists this file as pointing at "https://security.owncloud.com + YesWeHack bug bounty," and the Verification section states "diff confirms all five verbatim files are byte-identical to their docs-main sources." Diffing directly against docs-main: its SECURITY.md is 345 bytes / 11 lines; this PR's is 201 bytes / 8 lines. Missing, after line 8:
You can also report vulnerabilities through our YesWeHack bug bounty program:
**<https://yeswehack.com/programs/owncloud-bug-bounty-program>**
The other four "verbatim" files (CODE_OF_CONDUCT.md, CONTRIBUTING.md, SUPPORT.md, LICENSE) are genuinely byte-identical to docs-main — just this one dropped a paragraph.
Important
package.json's license value doesn't match the PR description or the sibling repos.
package.json:5 adds "license": "AGPL-3.0-or-later", but the PR description says it adds "license": "AGPL-3.0", "consistent with... the sibling docs repos." Checked all four: docs-main, docs-server, docs-webui, docs-ui all use the bare string "AGPL-3.0". Either change the value to match, or update the description.
Suggestion
Stale note in the PR description. "Two things for the OSPO to note," item 2, about site.yml:6 pointing at the prototype's personal fork — that was already fixed by #98 (merged 2026-08-21). Worth removing so reviewers don't chase an already-closed issue.
Verified clean
agents.md's architecture claims (extension file names inantora-extensions//asciidoc-extensions/,sync/contents,test/*.test.jsglob, per-version content folders, "skip withoutpublic/" test behavior) all match the live repo exactly..github/workflows/lint-pr-title.yml's pinned SHA foramannn/action-semantic-pull-requestresolves exactly tov6.1.1, genuinely the action's latest release; theconcurrencyblock matchesci.yml's existing style.- README's live-URL and branch-model fixes now agree with the repo's actual default branch and
site.yml. - Root-level Markdown is confirmed outside Antora's
start_paths, so it can't affect the site build.
🤖 Generated with Claude Code
The H1 dated from the prototype phase and read as a caveat rather than a name. The monorepo/experimental framing already lives in the intro paragraph and the "What changed vs. the legacy setup" table, so nothing is lost. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
Reverses the "dead link" bullet of 12ab788, which dropped the YesWeHack paragraph from SECURITY.md and the bounty line from README.md because the URL 404s. The 404 is real, but it is an org-wide baseline problem, not a defect of this repo: ~157 files across owncloud carry the same URL, and the community health files exist precisely to be byte-identical copies of the docs-main baseline. Diverging one repo buys a working link at the cost of that rule. SECURITY.md is byte-identical to owncloud/docs-main again (345 bytes, sha256 3e6f3d8ddaf75f6876dcec389587eec9ef31c0fd4dbdab94a15f0ca3f911de9c), and the README Security section matches the upstream template. Fixing the URL belongs to the OSPO as a single org-wide change. The other three bullets of 12ab788 (branch model, Actions policy, npm test) stand unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
|
@dj4oC thanks — all three findings were accurate. Addressed in 20e79c5 and 953e1f0, plus a PR-description rewrite. 1.
|
Why
This repo superseded the archived per-product
docs-*repos, but it never received the OSPO community health rollout v2 that the rest of the org got on 2026-06-22 (docs-main82dbaaf,docs-serverdc082e0). Becauseowncloud/.githubholds no org-default community health files, nothing was inherited — so this public repo has been publishing AGPL-3.0-derived documentation with noLICENSEfile at all.It is already registered in the control plane (
owncloud/admin→safe-settings/.github/repos/docs.owncloud.com.yml,codeowners/ownership.yml→@owncloud/docs-maintainers); only the in-repo files were missing.Added verbatim from
owncloud/docs-mainThese are byte-identical across the docs family (verified with
diff), so they are copied unchanged rather than reworded:LICENSEdocs-main,docs-server,docs-webuianddocs-uiall declare, i.e. the upstreams this content was synced fromCONTRIBUTING.mdCODE_OF_CONDUCT.mdSECURITY.mdSUPPORT.mdThe AGPL-3.0 declaration documents the repo's current license — it is not a relicensing.
Adapted, not copied
agents.md— keepsdocs-main's section order, retargeted to this monorepo:content/<product>/<version>/folders, Pagefind, the localantora-extensions//asciidoc-extensions/, the real npm scripts, Node 22,main(notmaster), and the two constraints specific to this repo (versions are folders, the upstream mirror is retired). Unlikedocs-main, this repo does have a test suite, so it says so.README.md— the existing monorepo design notes are kept in full; the OSPO v2 marker, the licence/OSPO badges and the template sections (Community & Support, Contributing, Security, License, About the OSPO, Apache-2.0 migration) are added around them. The H1 is also retitled fromownCloud Docs — Monorepo (experimental)toownCloud Documentation— the prototype-era title read as a caveat rather than a name, and the monorepo/experimental framing already lives in the intro paragraph and the "What changed vs. the legacy setup" table.Also
.github/workflows/lint-pr-title.ymlfromdocs-main—amannn/action-semantic-pull-request@48f2562(v6.1.1, confirmed the latest release, full-SHA pinned), plus an explicitpermissions: pull-requests: readand aconcurrencygroup to matchci.yml's style. This repo already uses Conventional Commit PR titles and squash-merges, but nothing enforced it.package.json'shomepage.package.jsongains"license": "AGPL-3.0-or-later", consistent with the newLICENSE. This is deliberately not the bareAGPL-3.0string the sibling docs repos use: that identifier is deprecated in the SPDX licence list precisely because it does not say whether later versions are permitted, and it was replaced by the explicitAGPL-3.0-only/AGPL-3.0-or-laterpair.-or-latermatches the FSF's recommended notice for this licence, which theLICENSEtemplate carries. Using a current identifier matters for thereuse lintpilot named as the OSPO's next step, since it validates against the live SPDX list. Worth aligning the sibling repos the same way in a follow-up.Deliberately out of scope
Each of these was checked and is either not part of the baseline or does not exist in the org:
REUSE.toml/LICENSES// SPDX headers (still a three-repo pilot —marketplace,marketplace-replacement,ocis— with noreuse-lintworkflow deployed anywhere);GOVERNANCE.mdandMAINTAINERS.md(present in zero ownCloud repos); aDCOfile (enforced by rulesets, not a file);CHANGELOG.md(product repos only);.github/settings.yml(legacy probot, superseded byowncloud/admin); issue/PR templates (only pre-OSPO copies exist, referencing retired label schemes and dead URLs)..github/CODEOWNERSis untouched — it is generated byowncloud/admin.Two things for the OSPO to note
.github/CODEOWNERS:2carriesSPDX-License-Identifier: Apache-2.0while this repo declares AGPL-3.0. That header is emitted by theowncloud/admingenerator for every repo it manages, so it is not fixable here.https://yeswehack.com/programs/owncloud-bug-bounty-programreturns 404, and no equivalent programme is discoverable on YesWeHack. It is nevertheless kept verbatim here, in bothSECURITY.mdandREADME.md, becausegh search code 'yeswehack org:owncloud'finds it in ~157 files across the org: diverging a single repo from a baseline that 36–48 repos share would trade the "copy verbatim, never reword" rule for one working link. The fix belongs to the OSPO as one org-wide change.security.owncloud.com— the actual reporting route — is live and listed first.Verification
diffconfirms all five verbatim files are byte-identical to theirdocs-mainsources (SECURITY.md: 345 bytes, sha2563e6f3d8ddaf75f6876dcec389587eec9ef31c0fd4dbdab94a15f0ca3f911de9c).npm test→ 17 pass, 0 fail (the 4go.php/latest-alias / redirect-target integration checks skip themselves unlesspublic/has been built, so build first or expect 13/4).package.jsonparses andnpm ci --dry-runexits 0; the workflow YAML parses and resolves to the expectedpermissions,concurrencyand pinned step.start_pathscover onlycontent/*, so the new root Markdown is outside the site build.gh repo view owncloud/docs.owncloud.com --json licenseInfoshould report AGPL-3.0 (currentlynull), and/communityshould show the checklist complete.🤖 Generated with Claude Code