Skip to content

fix(kyc): remove requireSeller from document submission endpoints (#626) - #723

Closed
Stephan-Thomas wants to merge 492 commits into
StellarState:mainfrom
Stephan-Thomas:fix/issue-626-kyc-endpoints-role
Closed

Stephan-Thomas wants to merge 492 commits into
StellarState:mainfrom
Stephan-Thomas:fix/issue-626-kyc-endpoints-role

Conversation

@Stephan-Thomas

@Stephan-Thomas Stephan-Thomas commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Description

Removes the requireSeller() middleware from the KYC document submission (POST /api/v1/kyc/) and resubmission (POST /api/v1/kyc/resubmit) endpoints in src/routes/kyc.routes.ts. This allows users with UserType.INVESTOR to submit and resubmit their KYC verification documents rather than incorrectly receiving 403 Forbidden: Seller role required.

Closes #626
Closes #630
Closes #634

Type of Change

  • ?? Bug fix (non-breaking change which fixes an issue)
  • ? New feature (non-breaking change which adds functionality)
  • ?? Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • ?? Documentation update
  • ?? UI/UX improvement
  • ?? Code refactoring
  • ? Test addition or update
  • ?? Configuration change

Checklist

  • All GitHub Actions workflows are green on this PR (required for merge)
  • Commit messages follow Conventional Commits ( eat:, ix:, chore:, etc.) - enforced by CI
  • No secrets, API keys, .env, or credentials committed (see CONTRIBUTING.md)
  • My code follows the code style of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published

Testing

No tests were run locally per instructions.

How to Test

  1. Authenticate as a user with UserType.INVESTOR to obtain a JWT.
  2. Send a POST request to /api/v1/kyc/ with valid KYC payload (documentType, documentNumber, ipfsDocumentUrl).
  3. Verify the request is accepted and does not return 403 Forbidden: Seller role required.
  4. Send a POST request to /api/v1/kyc/resubmit with updated KYC payload and verify it is accepted without role error.

Test Coverage

  • Unit tests added/updated
  • Integration tests added/updated
  • E2E tests added/updated (if applicable)
  • Manual testing completed

Screenshots (if applicable)

N/A

Additional Notes

Previously, both POST / and POST /resubmit required the seller role (requireSeller()), blocking investor KYC document verification. Document submission is now authenticated via createAuthMiddleware without restricting by seller role. Unused requireSeller import was also removed.

For Reviewers

  • Code quality and readability
  • Test coverage
  • Security implications
  • Performance impact
  • Breaking changes

The-Big-Danny and others added 30 commits September 26, 2026 09:30
Keep FAILED transitions and settlement trigger alongside upstream settlement events; adapt worker and test to updated types.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
….com/The-Big-Danny/SS-backend into Implement-invoice-maturity-detection

# Conflicts:
#	src/models/Invoice.model.ts
#	src/services/settlement.service.ts
…o P&L

Resolves StellarState#473 — POST/GET /investors acknowledgement endpoints, TERMS_VERSION
env bump invalidates prior acks, investment paths return 403 until acknowledged,
append-only acknowledgement history retained.

Resolves StellarState#477 — POST /invoices/:id/extension-request for sellers; admin PATCH
approval gate; atomic deadline update; investor notifications; reject second
pending request and funded/settled invoices (422).

Resolves StellarState#478 — GET /admin/metrics with date-range filter, status breakdown,
funded volume, avg funding time, active investors, settlement rate; 60s TTL
cache; admin IP-whitelist gate.

Resolves StellarState#479 — GET /portfolio with active/historical positions, summary
totals, realised P&L (settlement − principal, negative for cancelled), cursor
pagination.
Keep upstream Invoice @BeforeInsert/@BeforeUpdate hooks and the hardened
e2e beforeAll (setup inside try). Preserve this branch's settlement
.rejects assertions from StellarState#368.
…tor-portfolio-endpoint

feat(investor): Add portfolio endpoint for active positions and payout history
closes StellarState#542
closes StellarState#543
closes StellarState#544
closes StellarState#545

Shared foundation:
- TtlCache: Redis-mirrored TTL cache with in-process fallback
- ContractEventBus: topic-keyed handler registry dispatched by
  EventIndexerService after ingestion; a failing handler is logged
  and skipped so it cannot block the rest of the pipeline
- TypeORM projection repositories, idempotent on the on-chain id

StellarState#542: GET /api/v1/keys/:id/buy-limit (public, max_buy_per_tx and current
supply, 60s cache) plus the limit in GET /api/v1/keys/:id; cache is
invalidated by key_config_updated events.

StellarState#543: GET /api/v1/admin/acl and /acl/log, admin-only via role middleware,
projected from ACLUpdated events with add/remove history and a 5m cache.

StellarState#544: GET /api/v1/keys/:id/curve-migrations, creator-only for migrations
still behind the timelock, with proposed/applied params, timelock expiry
and an admin notification on execution.

StellarState#545: GET /api/v1/swaps/history (auth, buyer or seller, cursor paginated)
and public GET /api/v1/swaps/:id, projected from AtomicSwapExecuted.
…xtension-metrics-portfolio-473-479

feat(api): investor ack, deadline extensions, admin metrics, portfolio P&L
, StellarState#453

- Issue StellarState#449: Enhance auth flow and JWT claims with wallet, role, and
  userType; add GET /challenge?wallet= support alongside POST /challenge
  with query/body validation; support wallet and challenge aliases in verify.
- Issue StellarState#451: Align public invoice shape and marketplace query params
  (support cursor pagination, sort aliases, status filters, and mount
  /marketplace and /api/v1/marketplace routes).
- Issue StellarState#452: Implement seller dashboard API (GET /seller/dashboard and
  /api/v1/seller/dashboard) with invoice-level status breakdown and
  aggregate statistics scoped strictly to authenticated seller.
- Issue StellarState#453: Enable default wallet fallback for authenticated investor
  on POST /invoices/:id/invest and POST /invoices/:invoiceId/invest.
- Fix baseline test mock typing and entity metadata for clean build
  and test execution.
…uy-limit-ACL-curve-migrations-swaps

feat(onchain): add buy limit, ACL, curve migration and swap read models
- Add secondary market listings (model, migration, service, controller, routes)
  mounted at /api/v1/secondary for fraction trading
- Add investor watchlist (model, migration, service, controller, routes)
  mounted at /api/v1/watchlist
- Add KYC history tracking with KycHistory entity and migration
- Add notification data column and settlement notification dispatch
- Add hourly settlement worker (node-cron) wired into bootstrap lifecycle
- Extend KYC service/routes and invoice settlement routes
- Register new entities in test DataSource setups and extend in-memory user
  repositories with the new relations
- Fix duplicate idx_kyc_history_wallet index declaration that broke schema sync
Remove unused imports and dead service instantiations in src/index.ts,
admin.routes.ts, auth.routes.ts, dividends.routes.ts and
dividend-cycle.service.ts. The admin router keeps extensionService and
metricsService in its dependency contract but does not consume them yet,
so they are destructured with the repo's underscore convention.

Lint now passes clean, so the pre-commit hook and PR CI lint step succeed.
…arket-watchlist-settlement

feat: secondary market, watchlist, KYC history and settlement worker
…d onboarding

Adds four read models projected from Soroban contract events, each with its
own table, 30s cache, event-driven invalidation, HTTP surface and tests.
Closes StellarState#537, StellarState#538, StellarState#539, StellarState#540.

StellarState#537 — creator royalty earnings
- GET /api/v1/royalties/earnings: lifetime accruals, claims, outstanding
  balance and the per-transfer breakdown, scoped to the authenticated
  creator. Creator-only (SELLER / BOTH).
- GET /api/v1/royalties/history: cursor-paginated claims with tx hashes.
- transfer_limit is a page size rather than a cap: pages are followed until
  every event counted in transferCount has been read, so the per-transfer
  breakdown is never silently truncated.

StellarState#538 — dividend distribution
- GET /api/v1/dividends/claimable: claimable per cycle per holder.
- GET /api/v1/dividends/claims: cursor-paginated claim history.
- GET /api/v1/dividends/summary: earned / claimed / pending across all cycles.
- GET /api/v1/dividends/history stays backwards compatible: data is still
  the issuer's distribution list, with the holder's claims added as a
  sibling claims key.
- Allocation ids always include the recipient index, so one event's fan-out
  cannot collapse onto a single row.

StellarState#539 — gated-content subscription status
- GET /api/v1/subscriptions/status?wallet=&key_id= is public by design: a
  content gate has to answer before the visitor is known to the platform.
- The service is registered on the shared ContractEventBus so
  holding_changed / key_holding_changed actually evict the cache.
- key_id is encoded as an Address ScVal when it is a valid strkey and as a
  string ScVal otherwise.

StellarState#540 — onboarding tour completion
- GET /api/v1/onboarding/status: single indexed row lookup.
- POST /api/v1/onboarding/complete: wallet-scoped and idempotent, preserving
  the original completedAt.

Also repairs collateral damage from an earlier partial merge, all of which
blocked the lint and type-check pre-commit hooks:

- index.ts built acknowledgement, portfolio, extension and admin-metrics
  services but never passed them to createApp, so those routes were dead.
- admin.routes.ts imported createAuthMiddleware / requireAdminRole without
  applying them, leaving the analytics, metrics and ACL endpoints behind only
  an IP whitelist. The JWT admin role gate is now applied, with a valid
  x-admin-key still accepted so the older KYC and invoice review flows are
  unaffected. Restores GET /admin/metrics, the invoice-extension review
  endpoint and the ACL routes.
- keys.routes.ts lost GET /:id, GET /:id/buy-limit and
  GET /:id/curve-migrations; the services and OpenAPI entries were still
  there, so the handlers are restored.
- CreatorKey lost the eight column decorators the service layer and the
  existing migration 1732800000000 already expected.
- Removes dead imports in auth.routes.ts and dividend-cycle.service.ts.

Schema: three additive migrations, 1740000000004 through 1740000000006.

Tests: 61 new tests across five suites, all passing. Full suite 1395 passing
with 15 failing suites, a strict subset of the failures on the base branch
(verified by stashing and re-running); twelve of those baseline failures are
fixed by this branch and none are new.
…issue StellarState#186)

- Change error code from 'unauthorized_invoice_access' to 'forbidden' in invoice.service.ts
- Add integration test for seller invoice analytics access control (issue StellarState#186)
- Add integration test for invoice token holders authorization
- Add 1711000000000-AddMarketplaceIndexes.ts migration with 3 composite indexes
- Add 1711100000000-AddMarketplaceIndexes.ts migration with 3 composite indexes (uppercase names)
- Add integration test for marketplace indexes migration
…y-dividend-subscription-read-models

feat: on-chain read models for royalties, dividends, subscriptions and onboarding
…or payouts

- Add POST /api/v1/admin/invoices/:invoiceId/settle endpoint requiring admin JWT
- Validate invoice status is Funded before proceeding
- Submit settle_escrow contract call via Soroban RPC
- Record per-investor payout amounts in investor_payouts table after on-chain confirmation
- Transition invoice status to Settled and notify all investors via notification queue
- Add InvestorPayout model and migration
- Add admin authentication middleware

closes StellarState#454
- Add 'insufficient_role' to AuthFailureReason type
- Move InvestorPayoutStatus enum before class usage
- Fix import paths in settlement.routes.ts (../../ instead of ../)
- Fix AdminSettleInvoiceResult return type (status as const)
dee-john and others added 3 commits October 22, 2026 09:53
- StellarState#717: Preserve funded volume in analytics after investments settle
- StellarState#714: Prevent stale fee cache refill after schedule invalidation
- Currency conversion: Configure valid 56-char quote asset issuer
- Snapshot scheduler: Fix reporting day boundary with half-open UTC interval
- Fix CI compilation errors in auth middleware and indexer views
@drips-wave

drips-wave Bot commented Oct 22, 2026

Copy link
Copy Markdown

@Stephan-Thomas 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

TS-mfon and others added 25 commits October 22, 2026 15:22
…latform-fixes

fix: resolve analytics volume, fee cache race, quote asset issuer, an…
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…arding-yield-alert-indexing

fix: normalize Horizon transaction responses (StellarState#259)
…ayout-intent

Fix/616 settlement payout intent
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…rket-ownership-transfer

Fix/620 secondary market ownership transfer
@TS-mfon TS-mfon closed this Oct 27, 2026
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.