Skip to main content

Expert portal

Fixture data

Expert portal

What experts can do today, and exactly what is missing.

Where the work happens today

Live

Everyone who can reach this portal is staff — the route guard requires employee standing and a BACKOFFICE_EXPERT_ROLES role. Expert content is therefore authored and reviewed through the admin surfaces below, by an operator, on the expert’s behalf. Each still needs its own admin role.

The one contract that unblocks most of this

Almost every capability below is blocked on the same thing — resolving the signed-in principal to an expert. content.blog_authors.user_id already exists and is UNIQUE; nothing reads it.

GET /admin/content/experts/me → { author_id, display_name, slug, professional_title, status, verified_at, reward_enabled }

Deferred — no endpoint exists

6 capabilities

Each card names what an expert cannot do and the exact endpoint that has to exist first. Nothing here is clickable, because there is nothing to call. Where a card is marked data exists, the underlying rows are already being written and only the read is missing.

My profile & credentials

Deferred

An expert cannot view or edit their own byline, professional title, bio, or credentials. No endpoint maps the signed-in user to a content.blog_authors row. content.blog_authors.user_id exists and is UNIQUE, but no service reads it, so the portal cannot determine which expert is looking at it — and therefore cannot scope anything to them.

Missing endpoints

  • GET /admin/content/experts/me → { author_id, display_name, slug, professional_title, status, verified_at, reward_enabled }
  • PATCH /admin/content/experts/me → display_name, professional_title, bio_html, avatar, social links
  • GET /admin/content/experts/me/credentials → the expert's own degrees/licences + verification state

Would be backed by

content.blog_authorscontent.blog_author_credentials

My blog drafts

Deferred

An expert cannot see or write their own articles. content-service's admin post list DOES accept an `author_id` filter, so the read itself is nearly there — but without the identity mapping above the portal cannot supply the right author_id, and the existing admin editor is gated by ContentAdmin (an operator allowlist), not by authorship.

Missing endpoints

  • GET /admin/content/experts/me → { author_id, display_name, slug, professional_title, status, verified_at, reward_enabled }
  • An expert-scoped authorization mode on /admin/content/posts/* that permits the AUTHOR of a post (not only a ContentAdmin operator) to read and edit their own drafts

Would be backed by

content.blog_postscontent.blog_post_revisions

Submit an article for review

Data existsDeferred

The editorial and medical review workflow itself is now REAL (P9-12: submit → approve / request-changes / reject, each writing an attributable content.blog_post_reviews decision, with self-review refused and medical sign-off requiring a verified expert). What is missing is only the expert-facing door to it: the transitions are gated by ContentAdmin, so an expert cannot submit their own draft.

Missing endpoint

  • POST /admin/content/posts/{id}/submit-review authorized for the post's AUTHOR, not only a ContentAdmin operator

Would be backed by

content.blog_postscontent.blog_post_reviews

Request a coupon

Deferred

coupon.coupons carries expert_author_id, requested_by_user_id and a draft → pending_approval → approved lifecycle, and approval-service already accepts the `expert_coupon` action type. Nothing produces such a request, and no endpoint lets a non-operator create a coupon, so an expert cannot ask for one.

Missing endpoint

  • POST /admin/coupons/requests (expert-authenticated) → creates a draft coupon with expert_author_id + requested_by_user_id set, then an approval-service `expert_coupon` request

Would be backed by

coupon.couponsapproval.approval_requests

My attributed sales

Data existsDeferred

The DATA now exists: as of P9-05, checkout writes coupon.coupon_redemptions with expert_author_id, plus one coupon.coupon_redemption_items row per attributed order line (product, variant, quantity, item subtotal, discount, attributed sale). What is missing is a read: no service queries either table, so neither an expert nor an operator can see the totals. Nothing here should be shown until that endpoint exists — the previous portal displayed fixture numbers.

Missing endpoint

  • GET /admin/coupons/attribution?expert_author_id&from&to → per-expert attributed orders / sales / discount totals, and the per-product breakdown

Would be backed by

coupon.coupon_redemptionscoupon.coupon_redemption_items

My rewards & payouts

Deferred

content.expert_reward_rules / expert_reward_ledger / expert_reward_payouts exist but no accrual ever runs and no endpoint reads them, so there is no reward balance to show. (payment-service /rewards/* is the CUSTOMER loyalty wallet — a different domain entirely; it must not be reused to imply expert earnings.)

Missing endpoints

  • A reward accrual worker over content.expert_reward_rules
  • GET /admin/content/experts/me/rewards → ledger + balance by status
  • GET /admin/content/experts/me/payouts → payout history

Would be backed by

content.expert_reward_rulescontent.expert_reward_ledgercontent.expert_reward_payouts