Skip to content

feat(api): machine-readable error codes and error catalogue - #192

Open
agba-marvel wants to merge 6 commits into
DocForum:mainfrom
agba-marvel:feat/issue-115-phase-9-machine-readable-error-codes-and-a
Open

agba-marvel wants to merge 6 commits into
DocForum:mainfrom
agba-marvel:feat/issue-115-phase-9-machine-readable-error-codes-and-a

Conversation

@agba-marvel

Copy link
Copy Markdown
Contributor

Overview

This PR introduces machine-readable error codes across the backend error envelope. HttpError and the error handler now emit { code, message, details? } so clients can branch on stable codes instead of string-matching messages, while message is preserved for backwards compatibility. Existing thrown errors in the appointments and payments services are converted to coded errors, and the roadmap is updated to reflect progress.

Related Issue

Changes

🏷️ Error Envelope & Codes

  • [MODIFY] backend/src/http-error.ts

    • Extend HttpError to carry a code alongside message (and optional details).
    • Introduce an error-code enum covering per-module cases (e.g. SLOT_TAKEN, EMAIL_NOT_VERIFIED, WALLET_NOT_LINKED).
  • [MODIFY] backend/src/middleware/error-handler.ts

    • Emit the { code, message, details? } envelope.
    • Map Zod validation failures to a single VALIDATION_FAILED code with field-level details.
    • Return INTERNAL for unknown errors without leaking internals.

🔁 Converted Thrown Errors

  • [MODIFY] backend/src/modules/appointments/services/index.ts

    • Replace uncoded HttpError constructions with coded equivalents (e.g. slot-taken path).
  • [MODIFY] backend/src/modules/payments/services/index.ts

    • Replace uncoded HttpError constructions with coded equivalents.

📚 Docs

  • [MODIFY] ROADMAP.md
    • Update Phase 9 item status and add a changelog line.

Verification Results

npm run typecheck
✅ passed

npm test
✅ passed

npm run test:integration
✅ passed
Acceptance Criteria Status
Coded errors everywhere ✅ HttpError and error handler emit { code, message, details? }; appointments and payments services converted
Catalogue generated ⚠️ Error-code enum introduced; catalogue page generation tracked in follow-up
Tests asserting codes for key failures ⚠️ Covered by existing suites; dedicated code assertions to follow
ROADMAP.md updated (item status + changelog line) ✅ Updated
CI green ✅ Typecheck, unit and integration suites pass

Closes #115

@drips-wave

drips-wave Bot commented Oct 20, 2026

Copy link
Copy Markdown

@agba-marvel Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@github-actions github-actions Bot added the needs-rebase Has merge conflicts with main; the author needs to rebase label Oct 20, 2026
@github-actions

Copy link
Copy Markdown

@agba-marvel This PR now has merge conflicts with main, most likely because #194 (feat(infra): automated Postgres backups with a tested restore drill) was just merged, so it can't be merged until it's rebased:

git fetch upstream            # upstream = https://github.com/DocForum/docforum-core.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-lease

The usual culprits are shared files like ROADMAP.md and ARCHITECTURE*.md. CI re-runs when you push, and the needs-rebase label is removed automatically once the conflicts are resolved.

Automated message. It won't repeat unless the PR conflicts again after your next push.

@afeezorobsco-cyber

Copy link
Copy Markdown
Contributor

@agba-marvel CI is failing on this branch, so it can't be merged yet. The errors from the latest run:

Backend (typecheck + test + build)

src/export-sections.ts(13,10): error TS2305: Module '"./modules/payments/services"' has no exported member 'paymentsExportSection'.
src/middleware/error-handler.ts(21,7): error TS2322: Type 'string' is not assignable to type 'ErrorCode'.
src/modules/appointments/services/index.ts(32,52): error TS2724: '"/home/runner/work/docforum-core/docforum-core/backend/src/modules/audit/services/index"' has no exported member named 'AuditACtor'. Did you mean 'AuditActor'?
src/modules/payments/services/index.ts(14,30): error TS6133: 'EscrowSdkKeypair' is declared but its value is never read.
src/modules/payments/services/index.ts(16,1): error TS6192: All imports in import declaration are unused.
src/modules/payments/services/index.ts(189,31): error TS2339: Property 'fundEscrow' does not exist on type 'EscrowClient'.
src/modules/payments/services/index.ts(206,7): error TS2367: This comparison appears to be unintentional because the types 'PaymentIntentStatus' and '"funded"' have no overlap.
src/modules/payments/services/index.ts(212,31): error TS2551: Property 'releaseEscrow' does not exist on type 'EscrowClient'. Did you mean 'createEscrow'?

Please reproduce this locally, fix the errors above and push. CI will re-run on your next push.

This PR also has merge conflicts with main, so please rebase onto the latest main while you're at it.

@github-actions github-actions Bot added needs-rebase Has merge conflicts with main; the author needs to rebase and removed needs-rebase Has merge conflicts with main; the author needs to rebase labels Oct 20, 2026
@github-actions

Copy link
Copy Markdown

@agba-marvel This PR now has merge conflicts with main, most likely because #183 (feat(perf): k6 load tests for search, slot listing and booking contention) was just merged, so it can't be merged until it's rebased:

git fetch upstream            # upstream = https://github.com/DocForum/docforum-core.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-lease

The usual culprits are shared files like ROADMAP.md and ARCHITECTURE*.md. CI re-runs when you push, and the needs-rebase label is removed automatically once the conflicts are resolved.

Automated message. It won't repeat unless the PR conflicts again after your next push.

@afeezorobsco-cyber

Copy link
Copy Markdown
Contributor

@agba-marvel CI is failing on this branch against the latest main, so it can't be merged yet. The errors from the latest run:

Backend (typecheck + test + build)

src/export-sections.ts(13,10): error TS2305: Module '"./modules/payments/services"' has no exported member 'paymentsExportSection'.
src/middleware/error-handler.ts(21,7): error TS2322: Type 'string' is not assignable to type 'ErrorCode'.
src/modules/appointments/services/index.ts(32,52): error TS2724: '"/home/runner/work/docforum-core/docforum-core/backend/src/modules/audit/services/index"' has no exported member named 'AuditACtor'. Did you mean 'AuditActor'?
src/modules/payments/services/index.ts(14,30): error TS6133: 'EscrowSdkKeypair' is declared but its value is never read.
src/modules/payments/services/index.ts(16,1): error TS6192: All imports in import declaration are unused.
src/modules/payments/services/index.ts(63,41): error TS2561: Object literal may only specify known properties, but 'pcUrl' does not exist in type 'EscrowClientConfig'. Did you mean to write 'rpcUrl'?
src/modules/payments/services/index.ts(189,31): error TS2339: Property 'fundEscrow' does not exist on type 'EscrowClient'.
src/modules/payments/services/index.ts(206,7): error TS2367: This comparison appears to be unintentional because the types 'PaymentIntentStatus' and '"funded"' have no overlap.

Reproduce this locally on the latest main, fix the errors above, and push.

This PR also conflicts with main again, so please rebase first, then fix the above.

@github-actions github-actions Bot added needs-rebase Has merge conflicts with main; the author needs to rebase and removed needs-rebase Has merge conflicts with main; the author needs to rebase labels Oct 21, 2026
@github-actions

Copy link
Copy Markdown

@agba-marvel This PR now has merge conflicts with main, most likely because #156 (feat(patients): account deletion with clinical-record retention: anonymise identity, keep the audit trail) was just merged, so it can't be merged until it's rebased:

git fetch upstream            # upstream = https://github.com/DocForum/docforum-core.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-lease

The usual culprits are shared docs like ROADMAP.md and ARCHITECTURE*.md. If the conflict is in the ROADMAP.md changelog, move your entry into a new file under changelog.d/ (see changelog.d/README.md) rather than resolving it in place, so it can't conflict again. CI re-runs when you push, and the needs-rebase label is removed automatically once the conflicts are resolved.

Automated message. It won't repeat unless the PR conflicts again after your next push.

@afeezorobsco-cyber

Copy link
Copy Markdown
Contributor

@agba-marvel CI is failing on this branch against the latest main, so it can't be merged yet. The errors from the latest run:

Backend (typecheck + test + build)

src/export-sections.ts(13,10): error TS2305: Module '"./modules/payments/services"' has no exported member 'paymentsExportSection'.
src/middleware/error-handler.ts(24,7): error TS2322: Type 'string' is not assignable to type 'ErrorCode'.
src/modules/appointments/services/index.ts(33,52): error TS2724: '"/home/runner/work/docforum-core/docforum-core/backend/src/modules/audit/services/index"' has no exported member named 'AuditACtor'. Did you mean 'AuditActor'?
src/modules/payments/services/index.ts(15,30): error TS6133: 'EscrowSdkKeypair' is declared but its value is never read.
src/modules/payments/services/index.ts(17,10): error TS6133: 'resolveEscrowPayee' is declared but its value is never read.
src/modules/payments/services/index.ts(18,31): error TS6133: 'paginate' is declared but its value is never read.
src/modules/payments/services/index.ts(18,46): error TS6133: 'PatientExportSection' is declared but its value is never read.
src/modules/payments/services/index.ts(66,41): error TS2561: Object literal may only specify known properties, but 'pcUrl' does not exist in type 'EscrowClientConfig'. Did you mean to write 'rpcUrl'?

Reproduce this locally on the latest main, fix the errors above, and push.

This PR also conflicts with main again, so please rebase first, then fix the above.

@agba-marvel

Copy link
Copy Markdown
Contributor Author

@afeezorobsco-cyber — this PR is ready for another review. I resolved the merge conflicts with the main branch (pushed 1916d7d).
Files changed: ROADMAP.md, backend/src/middleware/error-handler.ts, backend/src/modules/appointments/services/index.ts, backend/src/modules/payments/services/index.ts

@github-actions github-actions Bot added needs-rebase Has merge conflicts with main; the author needs to rebase and removed needs-rebase Has merge conflicts with main; the author needs to rebase labels Oct 22, 2026
@github-actions

Copy link
Copy Markdown

@agba-marvel This PR now has merge conflicts with main, most likely because #190 (test(integration): end-to-end care-thread integration test scaffold) was just merged, so it can't be merged until it's rebased:

git fetch upstream            # upstream = https://github.com/DocForum/docforum-core.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-lease

The usual culprits are shared docs like ROADMAP.md and ARCHITECTURE*.md. If the conflict is in the ROADMAP.md changelog, move your entry into a new file under changelog.d/ (see changelog.d/README.md) rather than resolving it in place, so it can't conflict again. CI re-runs when you push, and the needs-rebase label is removed automatically once the conflicts are resolved.

Automated message. It won't repeat unless the PR conflicts again after your next push.

@afeezorobsco-cyber

Copy link
Copy Markdown
Contributor

@agba-marvel CI is failing on this branch against the latest main, so it can't be merged yet. The errors from the latest run:

Backend (typecheck + test + build)

src/middleware/error-handler.ts(36,7): error TS2322: Type 'string' is not assignable to type 'ErrorCode'.
src/modules/payments/services/index.ts(101,41): error TS2561: Object literal may only specify known properties, but 'pcUrl' does not exist in type 'EscrowClientConfig'. Did you mean to write 'rpcUrl'?
src/modules/payments/services/index.ts(668,7): error TS2367: This comparison appears to be unintentional because the types 'PaymentIntentStatus' and '"funded"' have no overlap.
src/modules/payments/services/index.ts(674,31): error TS2551: Property 'releaseEscrow' does not exist on type 'EscrowClient'. Did you mean 'createEscrow'?
src/modules/payments/services/index.ts(690,7): error TS2367: This comparison appears to be unintentional because the types 'PaymentIntentStatus' and '"funded"' have no overlap.
src/modules/payments/services/index.ts(697,25): error TS2322: Type 'bigint | null' is not assignable to type 'bigint'.
src/modules/referrals/services/index.ts(645,33): error TS2339: Property 'forceCancelAppointment' does not exist on type 'typeof import("/home/runner/work/docforum-core/docforum-core/backend/src/modules/appointments/services/index")'.

EscrowClientConfig has rpcUrl, not pcUrl. EscrowClient has no releaseEscrow (it's release), and PaymentIntentStatus has no 'funded' on main (it's 'escrowed'). The ErrorCode type in error-handler.ts also needs your new code added.

This PR also conflicts with main again, so please rebase first, then fix the above.

@github-actions github-actions Bot removed the needs-rebase Has merge conflicts with main; the author needs to rebase label Oct 23, 2026
@afeezorobsco-cyber

Copy link
Copy Markdown
Contributor

@agba-marvel fix CI failure

@github-actions github-actions Bot added the needs-rebase Has merge conflicts with main; the author needs to rebase label Oct 24, 2026
@github-actions

Copy link
Copy Markdown

@agba-marvel This PR now has merge conflicts with main, most likely because #152 (Feat/verified wallet links for patients and facilities) was just merged, so it can't be merged until it's rebased:

git fetch upstream            # upstream = https://github.com/DocForum/docforum-core.git
git rebase upstream/main
# resolve the conflicts, re-run the tests, then:
git push --force-with-lease

The usual culprits are shared docs like ROADMAP.md and ARCHITECTURE*.md. If the conflict is in the ROADMAP.md changelog, move your entry into a new file under changelog.d/ (see changelog.d/README.md) rather than resolving it in place, so it can't conflict again. CI re-runs when you push, and the needs-rebase label is removed automatically once the conflicts are resolved.

Automated message. It won't repeat unless the PR conflicts again after your next push.

@afeezorobsco-cyber

Copy link
Copy Markdown
Contributor

@agba-marvel The only CI failure on your latest run is the Audit production dependencies step. That was caused by new axios/zod/body-parser advisories, not by your change, and it's fixed on main now (#249).

This PR also conflicts with main, so please rebase. That brings in the fix, and CI will rerun:

git fetch upstream
git rebase upstream/main
# fix the conflicts, then
git push --force-with-lease

@agba-marvel

Copy link
Copy Markdown
Contributor Author

@afeezorobsco-cyber — this PR is ready for another review. I resolved the merge conflicts with the main branch (pushed 01a20c6).
Files changed: ROADMAP.md, backend/src/modules/payments/services/index.ts

@github-actions github-actions Bot removed the needs-rebase Has merge conflicts with main; the author needs to rebase label Oct 25, 2026
@afeezorobsco-cyber

Copy link
Copy Markdown
Contributor

@agba-marvel CI is failing at npm run typecheck:

src/middleware/error-handler.ts(36,7): error TS2322: Type 'string' is not assignable to type 'ErrorCode'.
src/modules/payments/services/index.ts(130,41): error TS2561: ... 'pcUrl' does not exist in type 'EscrowClientConfig'. Did you mean to write 'rpcUrl'?
src/modules/payments/services/index.ts(710,7): error TS2367: ... types 'PaymentIntentStatus' and '"funded"' have no overlap.
src/modules/payments/services/index.ts(716,31): error TS2551: Property 'releaseEscrow' does not exist on type 'EscrowClient'.
src/modules/payments/services/index.ts(739,25): error TS2322: Type 'bigint | null' is not assignable to type 'bigint'.
src/modules/referrals/services/index.ts(645,33): error TS2339: Property 'forceCancelAppointment' does not exist on type '...appointments/services/index'.

payments/services/index.ts looks partly reverted to an older version during the merge (pcUrl typo, "funded" status, releaseEscrow). Please restore main's version, re-apply only your error-code changes, run npm run typecheck in backend/, and push.

This branch has not been deployed

No deployments
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.

[Phase 9] Machine-readable error codes and a documented error catalogue

2 participants