fix(products): source products and entitlements from the registry, not hard-coded ids #25

Merged
sharang merged 1 commits from fix/product-key-mismatch into main 2026-09-02 09:47:53 +00:00
Owner

A started trial never showed as entitled. Two causes, both fixed here.

1. The live path never fetched entitlements at all

loadTenantForShell resolves fixture tenants first and, for a real tenant, returned a shim with entitled: [] and products: [] hard-coded. So entitled.includes(p.id) was false for everything, regardless of what the registry said. It now fetches /v1/catalog and /v1/entitlements (both best-effort — a failure degrades to an empty grid rather than 404-ing the page) and filters to enabled + not expired.

2. The ids could not match even in principle

The registry catalog offers certifai and compliance. The portal hard-coded compliance-scannera different product entirely, which lives in ~/workspace/compliance-scanner and is not in this catalog. The findings filter hard-coded the same wrong id.

The fix removes the class of bug, not one constant

Products are now derived from the registry catalog, and entitled is built from the same registry keys — so the two sides cannot drift apart again. The findings filter likewise derives from the tenants own products.

Verified against the live dev registry

/v1/catalog        -> [certifai, compliance]
start trial (acme, compliance) -> 201, expires 2026-09-16
/v1/entitlements   -> compliance (enabled)

entitled = [compliance]
entitled.includes("compliance") -> true
entitled.includes("certifai")   -> false

tsc --noEmit 0 · next build 0. Fixture tenants unaffected — they still carry their own products and the derived filter uses those.

Note: I started a real trial entitlement on the dev acme tenant to verify this end to end. It expires 2026-09-16 and can be revoked if unwanted.

**A started trial never showed as entitled.** Two causes, both fixed here. ### 1. The live path never fetched entitlements at all `loadTenantForShell` resolves fixture tenants first and, for a **real** tenant, returned a shim with `entitled: []` and `products: []` **hard-coded**. So `entitled.includes(p.id)` was false for everything, regardless of what the registry said. It now fetches `/v1/catalog` and `/v1/entitlements` (both best-effort — a failure degrades to an empty grid rather than 404-ing the page) and filters to enabled + not expired. ### 2. The ids could not match even in principle The registry catalog offers `certifai` and `compliance`. The portal hard-coded `compliance-scanner` — **a different product entirely**, which lives in `~/workspace/compliance-scanner` and is not in this catalog. The findings filter hard-coded the same wrong id. ## The fix removes the class of bug, not one constant Products are now derived from the registry catalog, and `entitled` is built from the **same** registry keys — so the two sides cannot drift apart again. The findings filter likewise derives from the tenants own products. ## Verified against the live dev registry ``` /v1/catalog -> [certifai, compliance] start trial (acme, compliance) -> 201, expires 2026-09-16 /v1/entitlements -> compliance (enabled) entitled = [compliance] entitled.includes("compliance") -> true entitled.includes("certifai") -> false ``` `tsc --noEmit` 0 · `next build` 0. Fixture tenants unaffected — they still carry their own products and the derived filter uses those. Note: I started a real trial entitlement on the dev `acme` tenant to verify this end to end. It expires 2026-09-16 and can be revoked if unwanted.
sharang added 1 commit 2026-09-02 08:46:14 +00:00
fix(products): source products and entitlements from the registry, not hard-coded ids
ci / test (pull_request) Successful in 10m23s
ci / e2e (pull_request) Blocked by required conditions
ci / shared (pull_request) Failing after 13s
ci / image (pull_request) Skipped
be7c59aa0f
A started trial never showed as entitled. Two causes, both fixed here.

1. The live path never fetched entitlements at all. loadTenantForShell resolves
   fixture tenants first and, for a REAL tenant, returned a shim with
   `entitled: []` and `products: []` hard-coded — so `entitled.includes(p.id)`
   was false for everything no matter what the registry said. It now fetches
   /v1/catalog and /v1/entitlements (both best-effort: a failure degrades to an
   empty grid rather than 404-ing the whole page) and filters entitlements to
   enabled + not expired.

2. The ids could not match even in principle. The registry catalog offers
   `certifai` and `compliance`; the portal's hard-coded list used
   `compliance-scanner` — a different product entirely (it lives in
   ~/workspace/compliance-scanner and is not in this catalog). The findings
   filter hard-coded the same wrong id.

The fix removes the class of bug rather than renaming one constant: products are
now derived from the registry catalog, and `entitled` is built from the SAME
registry keys, so the two sides cannot drift apart. The findings filter is
likewise derived from the tenant's own products.

Verified against the live dev registry: catalog returns
[certifai, compliance]; after starting a trial for acme, entitlements returns
`compliance` (enabled, expires 2026-09-16), and the mapping yields
entitled=[compliance] with entitled.includes("compliance")=true and
certifai=false. tsc --noEmit 0, next build 0.

Fixture tenants are unaffected — they still carry their own products, and the
derived filter uses those.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CNdLL9BdsWm7MCyui5ffPD
sharang merged commit faa6e83513 into main 2026-09-02 09:47:53 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: platform/portal#25