Verification Report
Generated: 2026-05-16T09:35:53.840500Z
Target: http://localhost:8080
Object triple: register=21 · schema=166 · object=25706ca9-c989-4d6b-9f7b-98cf1cc70639
Providers advertised: 24
Pass (non-crashing, 2xx or 503-degraded): 24 / 24
Generated by sequential curl probes against a live OpenRegister with 13 required Nextcloud apps installed (calendar, contacts, deck, mail, spreed, bookmarks, collectives, maps, photos, polls, forms, cospend, analytics, timemanager). The seeded integration-verification register holds a single probe object the harness targets.
What the harness checks
Per provider:
- OCS metadata — the provider appears in
ocs/v2.php/cloud/capabilitiesunderopenregister.integrations.providerswith the documented shape (id,label,group,enabled,storageStrategy,surfaces,authStatus). - Sub-resource probe —
GET /index.php/apps/openregister/api/objects/{register}/{schema}/{objectId}/integrations/{providerId}withOCS-APIRequest: truereturns a list envelope (HTTP 200,{items: [...]}) or the documenteddegraded source503 with a structured cause. - No hidden crashes — HTTP 500 anywhere fails the run. Provider exceptions like
NoVtodoCalendarExceptionmust be caught and converted to an empty list, not bubbled to the controller.
Earlier runs reported 412s across the board — that was a CSRF false-pass; the probe was being rejected at the session-CSRF guard before reaching any provider. The current harness sets OCS-APIRequest: true on every request.
Summary table
| ID | Group | Required app | Storage | Status | Shape | Latency | Notes |
|---|---|---|---|---|---|---|---|
calendar | comms | calendar | link-table | ✅ 200 | list-envelope | 610ms | — |
contacts | comms | contacts | link-table | ✅ 200 | list-envelope | 629ms | — |
email | comms | mail | link-table | ✅ 200 | list-envelope | 1159ms | — |
talk | comms | spreed | link-table | ✅ 200 | list-envelope | 599ms | — |
audit-trail | core | none | query-time | ✅ 200 | list-envelope | 579ms | — |
files | core | none | magic-column | ✅ 200 | list-envelope | 650ms | — |
notes | core | none | link-table | ✅ 200 | list-envelope | 599ms | — |
shares | core | none | query-time | ✅ 200 | list-envelope | 598ms | — |
tags | core | none | link-table | ✅ 200 | list-envelope | 639ms | — |
tasks | core | none | link-table | ✅ 200 | list-envelope | 596ms | — |
bookmarks | docs | bookmarks | link-table | ✅ 200 | list-envelope | 589ms | — |
collectives | docs | collectives | link-table | ✅ 200 | list-envelope | 613ms | — |
maps | docs | maps | link-table | ✅ 200 | list-envelope | 622ms | — |
photos | docs | photos | link-table | ✅ 200 | list-envelope | 596ms | — |
openproject | external | openconnector | external | ✅ 200 | list-envelope | 627ms | — |
xwiki | external | openconnector | external | ✅ 200 | list-envelope | 595ms | — |
activity | workflow | activity | query-time | ✅ 200 | list-envelope | 588ms | — |
analytics | workflow | analytics | link-table | ✅ 200 | list-envelope | 596ms | — |
cospend | workflow | cospend | link-table | ✅ 200 | list-envelope | 592ms | — |
deck | workflow | deck | link-table | ✅ 200 | list-envelope | 598ms | — |
flow | workflow | workflowengine | link-table | ✅ 200 | list-envelope | 599ms | — |
forms | workflow | forms | link-table | ✅ 200 | list-envelope | 597ms | — |
polls | workflow | polls | link-table | ✅ 200 | list-envelope | 581ms | — |
time-tracker | workflow | timemanager | link-table | ✅ 200 | list-envelope | 582ms | — |
Findings
- 24 / 24 providers return HTTP 200 with the documented
{items: []}list envelope. The seeded probe object has no linked upstream items in any leaf, so every list is empty — but the shape, the timing, and the success path are all proven. - 0 / 24 providers return HTTP 503. Both OpenConnector-backed externals (
xwiki+openproject) are wired against real local services indocker-compose.integration-verification.yml. See xwiki and openproject for the setup paths. - 0 / 24 providers crash. An earlier
tasksHTTP 500 —NoVtodoCalendarExceptionthrown when the user has no VTODO-capable calendar — was fixed in this run: the provider now catches the exception and returns an empty list, treating "no calendar yet" as a setup state rather than a server error.
Per-group breakdown
Group: core
audit-trail — Audit trail
- Required app:
none - Storage strategy:
query-time - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/audit-trail - Status: 200 (
list-envelope, 579ms)
files — Files
- Required app:
none - Storage strategy:
magic-column - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/files - Status: 200 (
list-envelope, 650ms)
notes — Notes
- Required app:
none - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/notes - Status: 200 (
list-envelope, 599ms)
shares — Shares
- Required app:
none - Storage strategy:
query-time - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/shares - Status: 200 (
list-envelope, 598ms)
tags — Tags
- Required app:
none - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/tags - Status: 200 (
list-envelope, 639ms)
tasks — Tasks
- Required app:
none - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/tasks - Status: 200 (
list-envelope, 596ms)
Group: comms
calendar — Meetings
- Required app:
calendar - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/calendar - Status: 200 (
list-envelope, 610ms)
contacts — Contacts
- Required app:
contacts - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/contacts - Status: 200 (
list-envelope, 629ms)
email — Emails
- Required app:
mail - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/email - Status: 200 (
list-envelope, 1159ms)
talk — Chat
- Required app:
spreed - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/talk - Status: 200 (
list-envelope, 599ms)
Group: docs
bookmarks — Bookmarks
- Required app:
bookmarks - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/bookmarks - Status: 200 (
list-envelope, 589ms)
collectives — Knowledge
- Required app:
collectives - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/collectives - Status: 200 (
list-envelope, 613ms)
maps — Location
- Required app:
maps - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/maps - Status: 200 (
list-envelope, 622ms)
photos — Photos
- Required app:
photos - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/photos - Status: 200 (
list-envelope, 596ms)
Group: workflow
activity — Activity
- Required app:
activity - Storage strategy:
query-time - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/activity - Status: 200 (
list-envelope, 588ms)
analytics — Analytics
- Required app:
analytics - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/analytics - Status: 200 (
list-envelope, 596ms)
cospend — Costs
- Required app:
cospend - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/cospend - Status: 200 (
list-envelope, 592ms)
deck — Cards
- Required app:
deck - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/deck - Status: 200 (
list-envelope, 598ms)
flow — Automation
- Required app:
workflowengine - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/flow - Status: 200 (
list-envelope, 599ms)
forms — Forms
- Required app:
forms - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/forms - Status: 200 (
list-envelope, 597ms)
polls — Polls
- Required app:
polls - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/polls - Status: 200 (
list-envelope, 581ms)
time-tracker — Time
- Required app:
timemanager - Storage strategy:
link-table - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/time-tracker - Status: 200 (
list-envelope, 582ms)
Group: external
openproject — Projects
- Required app:
openconnector - Storage strategy:
external - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/openproject - Status: 200 (
list-envelope, 627ms)
xwiki — Articles
- Required app:
openconnector - Storage strategy:
external - Surfaces:
user-dashboard,app-dashboard,detail-page,single-entity - Auth:
ok/configured - Probe:
GET /index.php/apps/openregister/api/objects/21/166/25706ca9-c989-4d6b-9f7b-98cf1cc70639/integrations/xwiki - Status: 200 (
list-envelope, 595ms)
Reproducing locally
Against the OpenRegister dev container (admin:admin, default NEXTCLOUD_URL):
# Seed a sandbox register + schema + probe object (one-time)
curl -u admin:admin -H 'OCS-APIRequest: true' -X POST \\
http://localhost:8080/index.php/apps/openregister/api/registers \\
-d '{"slug":"integration-verification","title":"Integration Verification","schemas":[]}'
# PHPUnit — provider metadata + delegation tests (50 tests)
./vendor/bin/phpunit --testsuite "Unit Tests" --filter "LeafProvidersMetadataTest|XwikiProviderTest"
# Playwright — registry contract + per-leaf endpoint probe
NEXTCLOUD_URL=http://localhost:8080 npx playwright test tests/e2e/integration-registry.spec.ts --project=chromium
# Playwright — verification harness (writes tests/e2e/leaf-verification.json)
NEXTCLOUD_URL=http://localhost:8080 npx playwright test tests/e2e/leaf-verification.spec.ts --project=chromium
Related
- Leaf system overview
- Pluggable Integration Registry (ADR-019)
- Source spec:
tests/e2e/leaf-verification.spec.ts