You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
FuzeFront's design intent is that Authentik, Permit, and Stripe are internal implementation details wrapped by FuzeFront's own APIs — consumer products integrate with FuzeFront, not with the vendors. Today that holds for Stripe (billing-service wraps it; the Mendys datasets marketplace checks out via /api/v1/billing/*, holds no Stripe keys) and is being brought into line for Authentik (auth broker, #238 + MendysRobotics#215). Permit is the remaining leak: the datasets marketplace currently talks to Permit directly — its PermitClient calls the PDP sidecar (POST {PERMIT_PDP_URL}/allowed) for checks and the Permit cloud API (api.permit.io/v2/facts/...) for user sync + role assignment, using a shared PERMIT_API_KEY. That exposes the vendor, the PDP topology, and a broad cloud key to every product.
Proposed shape (to be frozen by contract-designer, contract-first)
A FuzeFront authorization API (in security-service, alongside the auth broker) that fronts Permit for family products:
POST /api/v1/authz/check → { allowed: boolean } — body { productKey, resource, action, resourceKey?, tenant? }; actor resolved from the FuzeFront session/token (same trusted-actor model as billing-service), never a raw user id from the caller. FuzeFront namespaces to <product>_<Resource> internally (the PRODUCT_NS_SEP convention from fix(permit): product-namespace separator '.' → '_' (Permit rejects dots) #237) so products pass bare resource/action.
POST /api/v1/authz/roles:assign (+ :revoke) — assign a product role to a user in a tenant; product-scoped, authorized by the internal token, so a product can only touch its own <productKey>_* roles.
Optional POST /api/v1/authz/users:sync (or fold identity sync into the auth-broker callback so a separate call isn't needed).
Auth: BILLING_INTERNAL_TOKEN-style per-consumer internal token + trusted actor headers (reuse the billing-service middleware pattern). Products never receive PERMIT_API_KEY or the PDP URL.
Error surface + fail-closed semantics defined in the contract (a PDP/vendor error is a deny).
Generate a @fuzefront/authz-client package (mirrors @fuzefront/billing-client).
Scope notes
Contract-first: freeze the OpenAPI before implementation; the product policy registration (resources/roles per product, e.g. mendys-datasets) stays server-side as it is today (backend/src/permit/products/*.policy.ts) — this issue is about the runtime check/assign surface, not schema sync.
Keep the direct-PDP path working until the wrapped API is proven, so nothing regresses.
Consumer-side migration for the marketplace is tracked in the companion MendysRobotics issue (linked below).
Why
FuzeFront's design intent is that Authentik, Permit, and Stripe are internal implementation details wrapped by FuzeFront's own APIs — consumer products integrate with FuzeFront, not with the vendors. Today that holds for Stripe (billing-service wraps it; the Mendys datasets marketplace checks out via
/api/v1/billing/*, holds no Stripe keys) and is being brought into line for Authentik (auth broker, #238 + MendysRobotics#215). Permit is the remaining leak: the datasets marketplace currently talks to Permit directly — itsPermitClientcalls the PDP sidecar (POST {PERMIT_PDP_URL}/allowed) for checks and the Permit cloud API (api.permit.io/v2/facts/...) for user sync + role assignment, using a sharedPERMIT_API_KEY. That exposes the vendor, the PDP topology, and a broad cloud key to every product.Proposed shape (to be frozen by contract-designer, contract-first)
A FuzeFront authorization API (in security-service, alongside the auth broker) that fronts Permit for family products:
POST /api/v1/authz/check→{ allowed: boolean }— body{ productKey, resource, action, resourceKey?, tenant? }; actor resolved from the FuzeFront session/token (same trusted-actor model as billing-service), never a raw user id from the caller. FuzeFront namespaces to<product>_<Resource>internally (thePRODUCT_NS_SEPconvention from fix(permit): product-namespace separator '.' → '_' (Permit rejects dots) #237) so products pass bare resource/action.POST /api/v1/authz/roles:assign(+:revoke) — assign a product role to a user in a tenant; product-scoped, authorized by the internal token, so a product can only touch its own<productKey>_*roles.POST /api/v1/authz/users:sync(or fold identity sync into the auth-broker callback so a separate call isn't needed).BILLING_INTERNAL_TOKEN-style per-consumer internal token + trusted actor headers (reuse the billing-service middleware pattern). Products never receivePERMIT_API_KEYor the PDP URL.@fuzefront/authz-clientpackage (mirrors@fuzefront/billing-client).Scope notes
mendys-datasets) stays server-side as it is today (backend/src/permit/products/*.policy.ts) — this issue is about the runtime check/assign surface, not schema sync.Acceptance criteria
PERMIT_API_KEY, or PDP URL in its own config.mendys-datasetspolicy (parity test), and fail closed on vendor error.@fuzefront/authz-clientpublished; contract lint + tests green.Companion (consumer side): MendysRobotics issue linked below. Related: #238 (auth broker), billing-service (the existing wrap-the-vendor precedent).
🤖 Generated with Claude Code