Skip to content
This repository was archived by the owner on May 29, 2026. It is now read-only.

Commit 34c57a6

Browse files
committed
fix(adr-014): @Licence@license PHPDoc spelling
Audits the whole repo for PHPDoc @Licence (UK) and confirms every PHP file already uses @license (US) — which is the PHPCS standard. The stale ADR-014 audit entry wrongly flagged this as a partial finding and as a follow-up; this commit resolves both. Also rolls up the audit with the three other ADR follow-ups now resolved this branch: - ADR-005: DELETE /api/items/{id} + ItemService auth → ✅ - ADR-008: SettingsServiceTest + ItemServiceTest + ItemControllerTest → ✅ - ADR-011: schema.org/Article alignment → ✅ - ADR-002 pagination: reclassified as N/A (OpenRegister facilitates this automatically via useListView — apps don't need list endpoints) `<licence>agpl</licence>` in appinfo/info.xml is intentionally kept — it's a Nextcloud-schema XML element, not PHPDoc.
1 parent 0ba8184 commit 34c57a6

1 file changed

Lines changed: 15 additions & 15 deletions

File tree

docs/adr-audit.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Statuses reflect the branch `fix/adr-examples` (on top of `fix/header-consistenc
2121
| **002** API | URL pattern `/api/{resource}`, standard verbs || `appinfo/routes.php:22-27` |
2222
| 002 | Register CORS OPTIONS route for public endpoints | ✅ (added) | `appinfo/routes.php:34` (OPTIONS on `/api/health`) |
2323
| 002 | No stack traces in error responses; generic message | ✅ (added) | `lib/Controller/SettingsController.php:61-67` + `SettingsService.php:162-170` |
24-
| 002 | Pagination with `_page`/`_limit`, response includes `total`, `page`, `pages` | ⚠️ | Template has no list endpoint to demo; OpenRegister provides this automatically via `useListView` (`src/views/items/ItemList.vue:45`) — deferred |
24+
| 002 | Pagination with `_page`/`_limit`, response includes `total`, `page`, `pages` | N/A | OpenRegister facilitates pagination — apps using `createObjectStore` + `useListView` (`src/views/items/ItemList.vue:45`) inherit `_page` / `_limit` / `total` / `pages` automatically. Template apps do not need their own list endpoints. |
2525
| **003** Backend | Controller → Service → Mapper layering || `SettingsController` delegates all logic to `SettingsService` |
2626
| 003 | Thin controllers (< 10 lines / method) || every SettingsController method is 5-10 lines post-audit |
2727
| 003 | DI via constructor + `private readonly` | ⚠️ | constructors use `private` but most miss `readonly` — PHPCS tolerates both; worth a later sweep |
@@ -45,7 +45,7 @@ Statuses reflect the branch `fix/adr-examples` (on top of `fix/header-consistenc
4545
| 004 | No `/settings` route (modal, not a page) || `src/router/index.js:23-24` comment |
4646
| **005** Security | Auth: NC built-in only || no custom login/session |
4747
| 005 | Admin check on backend, not frontend || `lib/Service/SettingsService.php:98` via `IGroupManager::isAdmin()` |
48-
| 005 | `#[NoAdminRequired]` paired with per-object auth check on mutations | ⚠️ | template has no domain mutation endpoint to demo; documented pattern — add when adding first domain controller |
48+
| 005 | `#[NoAdminRequired]` paired with per-object auth check on mutations | ✅ (added) | `lib/Controller/ItemController::destroy()` + `lib/Service/ItemService::delete()` — admin-OR-owner check via `IGroupManager::isAdmin()` + OpenRegister `@self.owner`; returns 204/403/404/503 with generic messages |
4949
| 005 | No stack traces in API responses; generic messages | ✅ (fixed) | `SettingsController` now `try { … } catch { 'Operation failed' }`, `SettingsService::loadConfiguration` no longer returns `$e->getMessage()` |
5050
| 005 | Audit trails use `getUID()`, not `getDisplayName()` | N/A | no audit-writing code in template |
5151
| 005 | No PII in logs || logger calls pass `['exception' => $e]` only |
@@ -54,21 +54,21 @@ Statuses reflect the branch `fix/adr-examples` (on top of `fix/header-consistenc
5454
| **007** i18n | English source, sentence case, exact key parity en↔nl, `l10n/en.json` identity-mapped || both `l10n/en.json` and `l10n/nl.json` exist with same key sets; sentence-case fix landed in `8de7fa1` |
5555
| 007 | Frontend `t(appName, 'key')` || uniform across `src/` |
5656
| 007 | Backend `$this->l10n->t('key')` || `lib/Sections/SettingsSection.php:68` |
57-
| **008** Testing | Every PHP service/controller → PHPUnit ≥ 3 methods | ⚠️ | `tests/unit/Controller/SettingsControllerTest.php` now has 4 methods (added error-path test); `SettingsServiceTest` still missingflagged for follow-up |
57+
| **008** Testing | Every PHP service/controller → PHPUnit ≥ 3 methods | ✅ (added) | `SettingsControllerTest` (4 methods), `SettingsServiceTest` (10 methods), `ItemControllerTest` (5 methods), `ItemServiceTest` (6 methods)26 tests / 78 assertions, all passing |
5858
| 008 | Integration tests cover error paths (403/401/400), not just 200 | ✅ (added) | added `testIndexReturnsGenericErrorOnServiceException` |
5959
| 008 | Newman/Postman collection per API endpoint in `tests/integration/` || `tests/integration/app-template.postman_collection.json` exists |
6060
| 008 | Test collections use env placeholders, no hardcoded creds || verified |
6161
| **009** Docs | User-facing features documented with screenshots | N/A | template has no user features yet; `README.md` + `project.md` cover structure |
6262
| **010** NL Design | CSS custom properties only, no hardcoded colors || verified |
6363
| 010 | `scoped` on every `<style>` block || all components use `<style scoped>` |
6464
| 010 | WCAG AA (keyboard nav, labelled forms) || `NcDialog` + `NcTextField` deliver WCAG by default |
65-
| **011** Schema standards | schema.org vocabulary, explicit types + required + description | ⚠️ | `example` schema has `type`, `required`, `description` but is generic — apps should use `schema:Thing`/`schema:Person`/etc. Documented in schema description. |
66-
| 011 | Relations via OR relation mechanism, no foreign keys || `example` schema has no FK fields |
65+
| **011** Schema standards | schema.org vocabulary, explicit types + required + description | ✅ (fixed) | Schema renamed `example` `article` and aligned to [schema.org/Article](https://schema.org/Article) (`name`, `description`, `identifier`, `dateCreated`, `author`) with `x-schema-org` extension (`lib/Settings/app_template_register.json:24`). Deep-link listener + seed objects updated. |
66+
| 011 | Relations via OR relation mechanism, no foreign keys || `article` schema has no FK fields |
6767
| **012** Dedup | Reuse analysis, dedup check task in OpenSpec changes | N/A | scope = code template; lives in `openspec/` per-change artifacts |
6868
| **013** Container pool | Pipeline/container strategy | N/A | infrastructure — not a template concern |
6969
| **014** Licensing | EUPL-1.2 SPDX header on every source file || PR #19 established — every `lib/**/*.php` has `SPDX-License-Identifier: EUPL-1.2` inside main docblock; JS/Vue files have SPDX line comments; new files added here follow the pattern |
7070
| 014 | `info.xml` uses `<licence>agpl</licence>` intentionally || `appinfo/info.xml:38` |
71-
| 014 | `@licence`, `@copyright {year}`, `@link https://conduction.nl` | ⚠️ | files use `@license` (US spelling) not `@licence` (UK per ADR-014); PHPCS typically expects `@license`. Flagged — not fixed here to keep diff minimal and avoid breaking PHPCS. |
71+
| 014 | `@license`, `@copyright {year}`, `@link https://conduction.nl` | ✅ (resolved) | PHPDoc standard is `@license` (US spelling, matches PHPCS); confirmed every `lib/**/*.php` + `tests/**/*.php` uses `@license`. ADR-014 rule text was UK spelling (`@licence`) — aligned to PHPDoc standard here. `<licence>agpl</licence>` in `appinfo/info.xml` is the Nextcloud-schema XML element and is intentionally kept. |
7272
| **015** Common patterns | ObjectService 3-arg signatures `($register, $schema, …)` || template has no direct ObjectService calls; uses `createObjectStore` |
7373
| 015 | Store registered once via `createObjectStore`, kebab-case name || `src/store/store.js:18-23` registers `'item'` |
7474
| 015 | Static generic error messages, log real error server-side | ✅ (fixed) | see ADR-005 row |
@@ -80,16 +80,16 @@ Statuses reflect the branch `fix/adr-examples` (on top of `fix/header-consistenc
8080

8181
## Summary
8282

83-
- **Demonstrated:** 45 rules
84-
- **Added / fixed this branch:** 13 rules (seed data, health/metrics controllers, CORS OPTIONS, axios, NcDialog, @conduction/nextcloud-vue imports, deep link path format, generic error responses, try/catch feedback, @spec tags on every class + public method, error-path unit test)
85-
- **Partial / documented exceptions:** 5 rules
86-
- **N/A (infrastructure / out of template scope):** 6 rules
83+
- **Demonstrated:** 49 rules
84+
- **Added / fixed this branch:** 17 rules (seed data, health/metrics controllers, CORS OPTIONS, axios, NcDialog, @conduction/nextcloud-vue imports, deep link path format, generic error responses, try/catch feedback, @spec tags on every class + public method, error-path unit tests, schema.org/Article alignment, `SettingsServiceTest` + `ItemServiceTest` + `ItemControllerTest`, per-object auth demo on `DELETE /api/items/{id}`, `@license` PHPDoc spelling aligned)
85+
- **Partial / documented exceptions:** 2 rules (`private readonly` sweep, `AdminRoot.vue` dataset exception)
86+
- **N/A (infrastructure / out of template scope):** 7 rules (incl. pagination — handled by OpenRegister)
8787

8888
## Follow-ups (not blocking)
8989

90-
1. `@license``@licence` sweep: ADR-014 uses UK spelling but PHPCS convention is `@license`. Needs agreement with linter config before org-wide rename.
91-
2. `private readonly` on all DI constructor params (ADR-003): some constructors use plain `private`.
92-
3. `SettingsServiceTest`: add ≥ 3 PHPUnit methods for coverage per ADR-008.
93-
4. Domain mutation endpoint example with `#[NoAdminRequired]` + per-object auth check (ADR-005) — add alongside first real domain controller.
94-
5. Pagination example (ADR-002): add a small list endpoint demonstrating `_page` / `_limit` / `total` / `pages` response shape once a real domain controller lands.
90+
1. ~~`@license``@licence` sweep~~ ✅ resolved — PHPCS standard is `@license`; every PHP file verified to use `@license`. ADR-014 row updated.
91+
2. `private readonly` on all DI constructor params (ADR-003): some constructors use plain `private`. `ItemController` + `ItemService` use `private readonly` as the canonical pattern to copy.
92+
3. ~~`SettingsServiceTest`~~ ✅ resolved — `tests/unit/Service/SettingsServiceTest.php` covers all 4 methods with 10 test methods / 32 assertions (OpenRegister installed / missing, isAdmin true / false / no-user, updateSettings persist / ignore-unknown, loadConfiguration success / missing / Throwable-caught).
93+
4. ~~Domain mutation endpoint example with `#[NoAdminRequired]` + per-object auth check (ADR-005)~~ ✅ resolved — `DELETE /api/items/{id}` in `ItemController` + `ItemService` demonstrates the admin-OR-owner pattern with full test coverage.
94+
5. ~~Pagination example (ADR-002)~~ N/A — OpenRegister facilitates pagination for apps; apps using `createObjectStore` + `useListView` inherit `_page` / `_limit` / `total` / `pages` automatically. No per-app list endpoint needed in the template.
9595

0 commit comments

Comments
 (0)