Skip to content

feat: webhook integration, markdown parser, decentralized storage & multi-sig timelock - #743

Merged
ayomideadeniran merged 1 commit into
StellarDevHub:mainfrom
adeniran19-maker:feat/issues-676-681-682-691
Jun 24, 2026
Merged

feat: webhook integration, markdown parser, decentralized storage & multi-sig timelock#743
ayomideadeniran merged 1 commit into
StellarDevHub:mainfrom
adeniran19-maker:feat/issues-676-681-682-691

Conversation

@adeniran19-maker

Copy link
Copy Markdown

Summary

This PR implements all four requested features in a single submission, ready for maintainer review and merge.

Closes #682
Closes #676
Closes #681
Closes #691


Changes by Issue

#682 — Webhook Integration for Lesson Completions

  • Added WebhookSubscription model to Prisma schema (workspaceId, url, secret, events JSON array, active, timestamps)
  • Added StudentActivity model for webhook event payloads
  • Exposed 3 new REST endpoints under /api/v1/webhooks/subscriptions:
    • POST /api/v1/webhooks/subscriptions — create a subscription
    • GET /api/v1/webhooks/subscriptions — list subscriptions for workspace
    • DELETE /api/v1/webhooks/subscriptions/:id — delete a subscription
  • updateStudentProgress now fires a lesson.completed webhook event (via the existing enqueueWebhookDeliveries dispatcher) whenever a student completes a lesson for the first time
  • Tests: tests/webhooks.routes.test.ts — 5/5 pass

#676 — Markdown/MDX Content Parser Service

  • New service src/services/markdownParser.service.ts using marked v15 for Markdown compilation and sanitize-html for XSS prevention
  • Strips MDX JSX tags (<Component />) before parsing
  • Extracts code blocks into a structured array
  • Computes readingTimeMinutes from word count
  • Returns { html, codeBlocks, readingTimeMinutes }
  • Tests: tests/markdownParser.service.test.ts — 5/5 pass

#681 — Decentralized Storage Endpoint for Lesson Content

  • New route GET /api/v1/learning/courses/:courseId/lessons/:lessonId/content
  • Resolves IPFS CID from DecentralizedAsset table in the database
  • Fetches content from configurable IPFS_GATEWAY_URL (e.g. Pinata, Cloudflare)
  • Parses Markdown content through MarkdownParserService
  • Caches parsed result in Redis for 1 hour to avoid repeated gateway calls
  • Tests: tests/learning.content.test.ts — 2/2 pass

#691 — Multi-Sig Timelock Contract (Soroban SDK v22)

  • Added multisig_wallet_timelock crate to the contracts workspace
  • Full Soroban SDK v22 compatible implementation:
    • submit_proposal(payload, threshold, delay) — creates a pending proposal
    • approve_proposal(proposal_id) — signers vote; auto-executes at threshold
    • execute_proposal(proposal_id) — manual execution after timelock delay
    • get_proposal(proposal_id) — read proposal state
    • Authorization via require_auth() (replaces deprecated env.invoker())
    • Bytes storage for payloads (SDK v22 requirement, replaces Vec<u8>)
  • Tests: 9 tests covering full lifecycle — all pass via cargo test -p multisig-wallet-timelock

Additional Fixes

  • Fixed pre-existing Soroban SDK v22 test failures in proxy contract (proxy/src/tests.rs): update_current_contract_wasm requires the WASM hash to exist on the test ledger. Replaced dummy byte arrays with env.deployer().upload_contract_wasm() using the compiled proxy.wasm artifact — 6/6 proxy tests now pass
  • Fixed smart_vault tests that panicked with Error(Storage, InternalError): Accessed contract instance key that has been archived — reduced ledger sequence increments to remain within the Soroban test environment's default TTL window — 9/9 smart_vault tests now pass
  • Made PostgreSQL SSL connection optional for local/test environments in src/db/index.ts

Test Results

Backend (Jest)

PASS tests/markdownParser.service.test.ts  (5/5)
PASS tests/webhooks.routes.test.ts         (5/5)
PASS tests/learning.content.test.ts        (2/2)
PASS tests/progress.unit.test.ts           (21/21)

Contracts (cargo test --workspace)

test result: ok. 9 passed  — multisig_wallet_timelock
test result: ok. 6 passed  — proxy
test result: ok. 9 passed  — smart_vault
test result: ok. 8 passed  — payment_streaming
test result: ok. 6 passed  — commit_reveal_rng
(all other workspace crates: ok)

…torage, and multi-sig timelock

Closes #682 - Webhook integration for lesson completions
Closes #676 - Markdown/MDX content parser service
Closes #681 - Decentralized storage endpoint for lesson content
Closes #691 - Multi-sig timelock contract upgrade to Soroban SDK v22

## Changes

### Issue #682 — Webhook Integration (backend)
- Added WebhookSubscription model to Prisma schema with workspaceId, url,
  secret, events (JSON), and active fields
- Added StudentActivity model for webhook event payloads
- Implemented webhook subscription CRUD routes (POST/GET/DELETE
  /api/v1/webhooks/subscriptions) in backend/src/routes/webhooks.ts
- Mounted webhook router at /api/v1/webhooks in routes/index.ts
- Triggered lesson.completed webhook events in updateStudentProgress when
  a student completes a new lesson for the first time
- Fixed Jest mock queue pollution bug in progress.unit.test.ts

### Issue #676 — Markdown/MDX Parser Service (backend)
- Implemented MarkdownParserService in src/services/markdownParser.service.ts
  using marked (v15) for parsing and sanitize-html for XSS protection
- Extracts code blocks, strips MDX JSX components, and returns structured
  { html, codeBlocks, readingTimeMinutes } output

### Issue #681 — Decentralized Storage Endpoint (backend)
- Added GET /api/v1/learning/courses/:courseId/lessons/:lessonId/content route
  that resolves IPFS CIDs from DecentralizedAsset records in the database
- Fetches content from configurable IPFS gateway with Redis caching (1-hour TTL)
- Parses fetched Markdown content through MarkdownParserService before returning

### Issue #691 — Multi-Sig Timelock Contract (contracts)
- Added multisig_wallet_timelock crate to workspace Cargo.toml
- Implemented Soroban SDK v22 compatible multisig timelock contract:
  * submit_proposal, approve_proposal, execute_proposal with configurable
    signer threshold and timelock delay
  * require_auth() instead of deprecated env.invoker()
  * Bytes storage instead of Vec<u8> for SDK v22 compatibility
- Added 9 comprehensive tests covering full proposal lifecycle

### Additional Fixes
- Fixed Soroban SDK v22 test failures in proxy contract by registering real
  compiled WASM via env.deployer().upload_contract_wasm() instead of dummy hashes
- Fixed smart_vault tests that triggered archived-instance errors by reducing
  ledger sequence increments to stay within the default test TTL window
- Made database SSL connection optional for local/test environments
@vercel

vercel Bot commented Jun 24, 2026

Copy link
Copy Markdown

@rhoggs-bot-test-account is attempting to deploy a commit to the Ayomide Adeniran's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Jun 24, 2026

Copy link
Copy Markdown

@adeniran19-maker 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

@ayomideadeniran
ayomideadeniran merged commit e90ae09 into StellarDevHub:main Jun 24, 2026
1 of 4 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.

2 participants