Skip to content

fix(events): event_message UUID links (post-cutover) — fixes pull/messages 500#991

Open
rubenvdlinde wants to merge 5 commits into
developmentfrom
fix/e2e-post-cutover-log-queries
Open

fix(events): event_message UUID links (post-cutover) — fixes pull/messages 500#991
rubenvdlinde wants to merge 5 commits into
developmentfrom
fix/e2e-post-cutover-log-queries

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

The bug (post-migration fallout)

GET /events/subscriptions/{id}/pull and /messages returned 500, failing 3 Newman assertions (the "Integration Tests (Newman)" CI check).

Root cause: the event_message schema carries both the legacy integer FK columns (eventId/consumerId/subscriptionId) and the post-cutover UUID reference fields (event/consumer/subscription). The OR migrator correctly populates the UUID fields (it maps legacy subscription_idsubscription), but the runtime code still used the integer fields:

  • EventService::createEventMessage() wrote the event/subscription UUIDs into the integer columns;
  • EventService::pullEvents() and EventsController::{subscriptionMessages,messages} filtered the integer columns with a UUID.

Postgres rejects a UUID in an integer column (invalid input syntax for type integer: "868d34ce-…") → 500.

Fix

Switched all four sites to the UUID reference fields (event/subscription/consumer). This is purely a post-cutover follow-through — the migrator already moved to these fields; the service/controller hadn't.

Verification

Against a fresh post-cutover instance (cutover migrations applied):

  • pull / messages for a real subscription: 500 → 200.
  • Newman: 94/94 assertions pass (was 91/94).
  • Regression E2E passes.

Audited the rest

Checked every other *Id => getUuid() write: synchronization_log/synchronization_contract/job_log use string FK fields (fine), and call_log writes use the string source field (fine). event_message was the only schema with the integer-FK/UUID mismatch.

The now-unused integer FK columns (event_message.{eventId,consumerId,subscriptionId}, call_log.{sourceId,actionId,synchronizationId}) are harmless for new data; dropping them is a separate schema-hygiene follow-up.

🤖 Generated with Claude Code

…fixes 500 on pull/messages

The event_message schema carries BOTH the legacy integer FK columns
(eventId/consumerId/subscriptionId) and the post-cutover UUID reference
fields (event/consumer/subscription). The OR migrator correctly populates
the UUID fields, but the runtime code still used the integer FK fields:

- createEventMessage() wrote the event/subscription UUIDs INTO the integer
  columns;
- pullEvents() + EventsController::{subscriptionMessages,messages} FILTERED
  the integer columns with a UUID.

Postgres rejects a UUID in an integer column
(`invalid input syntax for type integer`), so GET
/events/subscriptions/{id}/pull and /messages returned 500 (3 Newman
assertion failures). Switched all four sites to the UUID fields
(event/subscription/consumer). Newman: 94/94 assertions pass; the
regression E2E passes.

Note: the vestigial integer FK columns are now unused for new data — a
schema-hygiene cleanup (dropping them) is a separate follow-up.
calculateExpires() returns a ?\DateTime. Every call site formats it with
?->format('c') before saving to OpenRegister — except the error/test
sync-log data at line ~1056, which passed the raw DateTime. OR's
`expires` property is string|null, so saving an unformatted DateTime
threw a schema-validation error that escaped the controller's
`catch (Exception)` (it is not an \Exception), producing a corrupt HTTP
response — POST /synchronizations/{id}/test failed in CI with
"Parse Error: Invalid status code" (2 Newman assertions). Now formatted
like the others; the dry-run returns a clean response.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openconnector @ ac2903b

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 148/148
npm ✅ 581/581
PHPUnit ⏭️
Newman
Playwright

Quality workflow — 2026-05-26 07:50 UTC

Download the full PDF report from the workflow artifacts.

The synchronization_log and synchronization_contract_log schemas are
immutable/append-only in OpenRegister; the engine's legacy create-then-update
log pattern was rejected with 405 SCHEMA_APPEND_ONLY, breaking every sync run
and POST /synchronizations/{id}/test. Refactor the engine to build each log
fully in memory and persist it exactly once (append), correlating child
contract-logs to their parent via a generated executionId field rather than
the parent's OR-assigned id. Adds executionId to the two sync log schemas.

Verified locally: Newman 94/94; bogus-sync /test returns 400 (was 405).
Spec: openspec/changes/openconnector-write-once-immutable-logging.
- manifest-pages: add 'roadmap' to the allowed page types (FeaturesRoadmap),
  sync MANIFEST_PAGES to the current 25 pages, drop the removed Import page.
- manifest-pages console gate: replace the blanket 'ignore all 500/503' with
  URL-scoped filtering (NC-core user_status, OR graphql under php -S, removed
  /api/settings, __nonexistent__ sentinel) so a real openconnector endpoint
  5xx still fails the gate; surface the failing URL in error messages.
- synced-from-leaf: make the beforeAll seed robust (skip cleanly on failure
  rather than cascade) and dispose the API context on the early-return path.

Verified locally: manifest-pages 27/27, synced-from-leaf 3/3.
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