Skip to content

feat: implement usage statistics protocol client - #3

Merged
vitormattos merged 43 commits into
mainfrom
feat/protocol-v1-client
Sep 9, 2026
Merged

feat: implement usage statistics protocol client#3
vitormattos merged 43 commits into
mainfrom
feat/protocol-v1-client

Conversation

@vitormattos

@vitormattos vitormattos commented Sep 8, 2026

Copy link
Copy Markdown
Member

Summary

Implements the first reusable PHP client for Usage Statistics Protocol v1 and aligns the repository structure/tooling with LibreSign and usage_statistics_server conventions.

Protocol

  • typed Protocol v1 report objects
  • consent gating (unknown, enabled, disabled)
  • application-scoped pseudonymous installation IDs
  • reporting-period validation
  • endpoint validation and HTTP submission
  • accepted/rejected/transient response handling
  • no invented authentication, signing, handshake, or attestation

Composer and package structure

  • package name: librecodecoop/usage-statistics-client
  • PHP ^8.2
  • root composer.lock committed for reproducible project development/CI
  • bamarni/composer-bin-plugin at the root
  • isolated tooling under vendor-bin/
  • Composer scripts follow LibreSign/server conventions (lint, cs:check, cs:fix, test:unit, test:coverage, phpstan, psalm, phpmd, mutation:test)

The root lock file is versioned. vendor-bin/* keeps only its composer.json, matching the current server pattern.

Quality and tests

  • PHPUnit unit tests organized under tests/Unit/, mirroring src/ paths such as Transport/ and Exception/
  • tests focus on protocol/business invariants rather than a coverage threshold
  • DataProviders cover invalid identifiers, schema versions, consent states, timeouts, reporting periods, calendar-month boundaries, server rejection classes and invalid success responses
  • report and metric protocol limits are tested at their boundaries
  • consent, HTTP error classes, retry-after, timeout, serialization, endpoint safety and installation-ID stability are tested
  • Nextcloud coding standard via nextcloud/coding-standard
  • complementary PHPCS checks including PSR-1 and line-length hygiene
  • PHPStan at maximum level
  • Psalm at level 1
  • PHPMD
  • Infection mutation testing
  • Composer validation/audit
  • REUSE
  • namespace-scoping smoke test

Current Infection result: 100% mutation code coverage and 95% covered-code MSI. Both minMsi and minCoveredMsi are enforced at 95%.

PHPCPD was not added because it is obsolete/unmaintained; PHPMD is used for maintainability/complexity checks and Infection measures test effectiveness.

LibreSign readiness

The client was revalidated against the current LibreSign/3rdparty dependency model.

  • the scoping workflow uses the exact OCA\\Libresign\\Vendor prefix used by LibreSign
  • the smoke test loads and executes the client through OCA\\Libresign\\Vendor\\LibreCode\\UsageStatistics
  • the public API has no third-party runtime interfaces that would break after prefixing
  • PHP ^8.2 is compatible with LibreSign's current PHP 8.3 platform
  • docs/integration.md documents the LibreSign/Nextcloud adapter and ownership boundaries

The remaining LibreSign work is intentionally application-specific: consent persistence, metric/schema definition, endpoint configuration, background scheduling, a Nextcloud HTTP-client adapter, and adding the released package to LibreSign/3rdparty. The receiving server must also have the corresponding LibreSign schema registered.

A stable Composer tag should be published before production integration. Until then, only a temporary VCS/dev dependency can consume this branch.

CI

Replaces the monolithic ci.yml with separate workflow files following the Nextcloud/LibreSign workflow-template style:

  • Composer
  • PHP lint
  • PHP coding style
  • PHPUnit (PHP 8.2, 8.3, 8.4 and 8.5)
  • PHPStan
  • Psalm
  • PHPMD
  • Infection
  • REUSE
  • namespace scoping

All workflows are green on the current head.

Documentation, licensing and funding

  • AGPL-3.0-or-later
  • root COPYING
  • SPDX/REUSE metadata
  • .gitignore carries SPDX headers directly instead of being listed in REUSE.toml
  • CONTRIBUTING.md
  • README simplified; detailed rationale remains in docs/
  • .github/FUNDING.yml matches LibreSign and points GitHub Sponsors to libresign

Package vendor

The repository is expected to move to the LibreCodeCoop organization. Existing LibreCodeCoop packages and installation documentation use the librecodecoop/* Composer vendor convention, so this PR uses librecodecoop/usage-statistics-client rather than the personal vitormattos/* vendor.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>

Copy link
Copy Markdown
Member Author

CI status note

The first Actions run (on #1) exercised the same implementation chain and exposed three real issues: PHP 8.1 dependency resolution was blocked by PHP-Scoper requiring PHP 8.2, PHPCS found style/file-layout violations, and REUSE found missing metadata for .gitignore. Those issues were corrected in signed-off commits. The earlier run already had PHP 8.4 tests, PHP 8.5 tests, and the namespace-scoping smoke job passing.

After those fixes, connector-authored branch updates and newly opened replacement PRs did not emit any new GitHub Actions workflow run. I tried branch ref updates, Contents API updates, closing/reopening, and new PR heads; GitHub still reports no run for the current PR head. This is therefore an execution/trigger limitation of the authenticated integration, not a green CI claim.

The current head additionally adds a real 75% coverage gate, separates PHP-Scoper from the PHP 8.1 dependency matrix, normalizes response headers, locks the installation-ID derivation with a golden vector, removes an ambiguous package-version User-Agent, and hardens period/coverage helpers for strict static analysis. A normal user-authored push or rerun-capable workflow trigger should execute the configured matrix before merge.

vitormattos and others added 19 commits September 8, 2026 20:37
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
@vitormattos
vitormattos merged commit 410974f into main Sep 9, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant